mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-11 15:31:22 +02:00
Pruned defunct and unused contributions from Huawei
Change-Id: I8f1c611682e0f282bc41eb7a4ff4ff23b91a48e5
This commit is contained in:
parent
5c2807cf9d
commit
84d9fac856
@ -1,10 +0,0 @@
|
||||
osgi_jar_with_tests(
|
||||
deps = CORE_DEPS,
|
||||
)
|
||||
|
||||
onos_app(
|
||||
category = "Utility",
|
||||
description = "ONOS Cluster IP alias application.",
|
||||
title = "Cluster IP Alias",
|
||||
url = "http://onosproject.org",
|
||||
)
|
@ -1,211 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015-present Open Networking Foundation
|
||||
*
|
||||
* 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.cip;
|
||||
|
||||
import com.google.common.io.ByteStreams;
|
||||
import org.onosproject.cfg.ComponentConfigService;
|
||||
import org.onosproject.cluster.ClusterService;
|
||||
import org.onosproject.cluster.LeadershipEvent;
|
||||
import org.onosproject.cluster.LeadershipEventListener;
|
||||
import org.onosproject.cluster.LeadershipService;
|
||||
import org.onosproject.cluster.NodeId;
|
||||
import org.osgi.service.component.ComponentContext;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Deactivate;
|
||||
import org.osgi.service.component.annotations.Modified;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Dictionary;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
|
||||
import static com.google.common.base.Strings.isNullOrEmpty;
|
||||
import static org.onlab.util.Tools.get;
|
||||
import static org.onosproject.cip.OsgiPropertyConstants.ALIAS_ADAPTER;
|
||||
import static org.onosproject.cip.OsgiPropertyConstants.ALIAS_ADAPTER_DEFAULT;
|
||||
import static org.onosproject.cip.OsgiPropertyConstants.ALIAS_IP;
|
||||
import static org.onosproject.cip.OsgiPropertyConstants.ALIAS_IP_DEFAULT;
|
||||
import static org.onosproject.cip.OsgiPropertyConstants.ALIAS_MASK;
|
||||
import static org.onosproject.cip.OsgiPropertyConstants.ALIAS_MASK_DEFAULT;
|
||||
|
||||
/**
|
||||
* Manages cluster IP address alias.
|
||||
*
|
||||
* To use the application, simply install it on ONOS and then configure it
|
||||
* with the desired alias IP/mask/adapter configuration.
|
||||
*
|
||||
* If you are running it using upstart, you can also add the following
|
||||
* command to the /opt/onos/options file:
|
||||
*
|
||||
* sudo ifconfig eth0:0 down # use the desired alias adapter
|
||||
*
|
||||
* This will make sure that if the process is killed abruptly, the IP alias
|
||||
* will be dropped upon respawn.
|
||||
*/
|
||||
@Component(
|
||||
immediate = true,
|
||||
property = {
|
||||
ALIAS_IP + "=" + ALIAS_IP_DEFAULT,
|
||||
ALIAS_MASK + "=" + ALIAS_MASK_DEFAULT,
|
||||
ALIAS_ADAPTER + "=" + ALIAS_ADAPTER_DEFAULT
|
||||
}
|
||||
)
|
||||
public class ClusterIpManager {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private static final String CLUSTER_IP = "cluster/ip";
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected ClusterService clusterService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected LeadershipService leadershipService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected ComponentConfigService cfgService;
|
||||
|
||||
private final LeadershipEventListener listener = new InternalLeadershipListener();
|
||||
|
||||
private NodeId localId;
|
||||
private boolean wasLeader = false;
|
||||
|
||||
/** Alias IP address. */
|
||||
private String aliasIp = ALIAS_IP_DEFAULT;
|
||||
|
||||
/** Alias IP mask. */
|
||||
private String aliasMask = ALIAS_MASK_DEFAULT;
|
||||
|
||||
/** Alias IP adapter. */
|
||||
private String aliasAdapter = ALIAS_ADAPTER_DEFAULT;
|
||||
|
||||
@Activate
|
||||
protected void activate(ComponentContext context) {
|
||||
cfgService.registerProperties(getClass());
|
||||
|
||||
localId = clusterService.getLocalNode().id();
|
||||
processLeaderChange(leadershipService.getLeader(CLUSTER_IP));
|
||||
|
||||
leadershipService.addListener(listener);
|
||||
leadershipService.runForLeadership(CLUSTER_IP);
|
||||
log.info("Started");
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
protected void deactivate(ComponentContext context) {
|
||||
cfgService.unregisterProperties(getClass(), false);
|
||||
|
||||
removeIpAlias(aliasIp, aliasMask, aliasAdapter);
|
||||
|
||||
leadershipService.removeListener(listener);
|
||||
leadershipService.withdraw(CLUSTER_IP);
|
||||
log.info("Stopped");
|
||||
}
|
||||
|
||||
@Modified
|
||||
protected void modified(ComponentContext context) {
|
||||
log.info("Received configuration change...");
|
||||
Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
|
||||
String newIp = get(properties, ALIAS_IP);
|
||||
String newMask = get(properties, ALIAS_MASK);
|
||||
String newAdapter = get(properties, ALIAS_ADAPTER);
|
||||
|
||||
// Process any changes in the parameters...
|
||||
if (!Objects.equals(newIp, aliasIp) ||
|
||||
!Objects.equals(newMask, aliasMask) ||
|
||||
!Objects.equals(newAdapter, aliasAdapter)) {
|
||||
synchronized (this) {
|
||||
log.info("Reconfiguring with aliasIp={}, aliasMask={}, aliasAdapter={}, wasLeader={}",
|
||||
newIp, newMask, newAdapter, wasLeader);
|
||||
if (wasLeader) {
|
||||
removeIpAlias(aliasIp, aliasMask, aliasAdapter);
|
||||
addIpAlias(newIp, newMask, newAdapter);
|
||||
}
|
||||
aliasIp = newIp;
|
||||
aliasMask = newMask;
|
||||
aliasAdapter = newAdapter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void processLeaderChange(NodeId newLeader) {
|
||||
boolean isLeader = Objects.equals(newLeader, localId);
|
||||
log.info("Processing leadership change; wasLeader={}, isLeader={}", wasLeader, isLeader);
|
||||
if (!wasLeader && isLeader) {
|
||||
// Gaining leadership, so setup the IP alias
|
||||
addIpAlias(aliasIp, aliasMask, aliasAdapter);
|
||||
wasLeader = true;
|
||||
} else if (wasLeader && !isLeader) {
|
||||
// Losing leadership, so drop the IP alias
|
||||
removeIpAlias(aliasIp, aliasMask, aliasAdapter);
|
||||
wasLeader = false;
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void addIpAlias(String ip, String mask, String adapter) {
|
||||
if (!isNullOrEmpty(ip) && !isNullOrEmpty(mask) && !isNullOrEmpty(adapter)) {
|
||||
log.info("Adding IP alias {}/{} to {}", ip, mask, adapter);
|
||||
execute("sudo ifconfig " + adapter + " " + ip + " netmask " + mask + " up", false);
|
||||
execute("sudo /usr/sbin/arping -c 1 -I " + adapter + " " + ip, true);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void removeIpAlias(String ip, String mask, String adapter) {
|
||||
if (!isNullOrEmpty(ip) && !isNullOrEmpty(mask) && !isNullOrEmpty(adapter)) {
|
||||
log.info("Removing IP alias from {}", adapter, false);
|
||||
execute("sudo ifconfig " + adapter + " down", true);
|
||||
}
|
||||
}
|
||||
|
||||
private void execute(String command, boolean ignoreCode) {
|
||||
try {
|
||||
log.info("Executing [{}]", command);
|
||||
Process process = Runtime.getRuntime().exec(command);
|
||||
byte[] output = ByteStreams.toByteArray(process.getInputStream());
|
||||
byte[] error = ByteStreams.toByteArray(process.getErrorStream());
|
||||
int code = process.waitFor();
|
||||
if (code != 0 && !ignoreCode) {
|
||||
log.info("Command failed: status={}, output={}, error={}",
|
||||
code, new String(output), new String(error));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("Unable to execute command {}", command, e);
|
||||
} catch (InterruptedException e) {
|
||||
log.error("Interrupted executing command {}", command, e);
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
// Listens for leadership changes.
|
||||
private class InternalLeadershipListener implements LeadershipEventListener {
|
||||
|
||||
@Override
|
||||
public boolean isRelevant(LeadershipEvent event) {
|
||||
return CLUSTER_IP.equals(event.subject().topic());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void event(LeadershipEvent event) {
|
||||
processLeaderChange(event.subject().leaderNodeId());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018-present Open Networking Foundation
|
||||
*
|
||||
* 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.cip;
|
||||
|
||||
public final class OsgiPropertyConstants {
|
||||
private OsgiPropertyConstants() {
|
||||
}
|
||||
|
||||
static final String ALIAS_IP = "aliasIp";
|
||||
static final String ALIAS_IP_DEFAULT = "";
|
||||
|
||||
static final String ALIAS_MASK = "aliasMask";
|
||||
static final String ALIAS_MASK_DEFAULT = "255.255.0.0";
|
||||
|
||||
static final String ALIAS_ADAPTER = "aliasAdapter";
|
||||
static final String ALIAS_ADAPTER_DEFAULT = "eth0:0";
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015-present Open Networking Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Cluster IP Manager, which is responsible for managing the cluster IP
|
||||
* address alias.
|
||||
*/
|
||||
package org.onosproject.cip;
|
@ -1,26 +0,0 @@
|
||||
APPS = [
|
||||
"org.onosproject.configsync",
|
||||
"org.onosproject.yang",
|
||||
"org.onosproject.netconf",
|
||||
]
|
||||
|
||||
COMPILE_DEPS = CORE_DEPS + [
|
||||
"@onos_yang_model//jar",
|
||||
"@onos_yang_runtime//jar",
|
||||
"//protocols/netconf/api:onos-protocols-netconf-api",
|
||||
"//apps/config:onos-apps-config",
|
||||
"//apps/configsync:onos-apps-configsync",
|
||||
]
|
||||
|
||||
osgi_jar_with_tests(
|
||||
test_deps = TEST_ADAPTERS,
|
||||
deps = COMPILE_DEPS,
|
||||
)
|
||||
|
||||
onos_app(
|
||||
category = "Utility",
|
||||
description = "Application to support the Dynamic configuration service.",
|
||||
required_apps = APPS,
|
||||
title = "Dynamic Configuration Synchronizer for NETCONF",
|
||||
url = "http://onosproject.org",
|
||||
)
|
@ -1,139 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.d.config.sync.impl.netconf;
|
||||
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Deactivate;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.onosproject.d.config.sync.DeviceConfigSynchronizationProviderRegistry;
|
||||
import org.onosproject.d.config.sync.DeviceConfigSynchronizationProviderService;
|
||||
import org.onosproject.net.device.DeviceService;
|
||||
import org.onosproject.net.provider.ProviderId;
|
||||
import org.onosproject.netconf.NetconfController;
|
||||
import org.onosproject.yang.model.SchemaContextProvider;
|
||||
import org.onosproject.yang.runtime.YangRuntimeService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
|
||||
/**
|
||||
* Main component of Dynamic config synchronizer for NETCONF.
|
||||
*
|
||||
* <ul>
|
||||
* <li> bootstrap Active and Passive synchronization modules
|
||||
* <li> start background anti-entropy mechanism for offline device configuration
|
||||
* </ul>
|
||||
*/
|
||||
@Component(immediate = true)
|
||||
public class NetconfDeviceConfigSynchronizerComponent {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
/**
|
||||
* NETCONF dynamic config synchronizer provider ID.
|
||||
*/
|
||||
public static final ProviderId PID =
|
||||
new ProviderId("netconf", "org.onosproject.d.config.sync.netconf");
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected DeviceConfigSynchronizationProviderRegistry registry;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected NetconfController netconfController;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected YangRuntimeService yangRuntimeService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected SchemaContextProvider schemaContextProvider;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected DeviceService deviceService;
|
||||
|
||||
private NetconfDeviceConfigSynchronizerProvider provider;
|
||||
|
||||
private DeviceConfigSynchronizationProviderService providerService;
|
||||
|
||||
|
||||
@Activate
|
||||
protected void activate() {
|
||||
provider = new NetconfDeviceConfigSynchronizerProvider(PID, new InnerNetconfContext());
|
||||
providerService = registry.register(provider);
|
||||
|
||||
// TODO (Phase 2 or later)
|
||||
// listen to NETCONF events (new Device appeared, etc.)
|
||||
// for PASSIVE "state" synchronization upward
|
||||
|
||||
// TODO listen to DeviceEvents (Offline pre-configuration scenario)
|
||||
|
||||
// TODO background anti-entropy mechanism
|
||||
|
||||
log.info("Started");
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
protected void deactivate() {
|
||||
registry.unregister(provider);
|
||||
log.info("Stopped");
|
||||
}
|
||||
|
||||
/**
|
||||
* Context object to provide reference to OSGi services, etc.
|
||||
*/
|
||||
@Beta
|
||||
public static interface NetconfContext {
|
||||
|
||||
/**
|
||||
* Returns DeviceConfigSynchronizationProviderService interface.
|
||||
*
|
||||
* @return DeviceConfigSynchronizationProviderService
|
||||
*/
|
||||
DeviceConfigSynchronizationProviderService providerService();
|
||||
|
||||
SchemaContextProvider schemaContextProvider();
|
||||
|
||||
YangRuntimeService yangRuntime();
|
||||
|
||||
NetconfController netconfController();
|
||||
|
||||
}
|
||||
|
||||
class InnerNetconfContext implements NetconfContext {
|
||||
|
||||
@Override
|
||||
public NetconfController netconfController() {
|
||||
return netconfController;
|
||||
}
|
||||
|
||||
@Override
|
||||
public YangRuntimeService yangRuntime() {
|
||||
return yangRuntimeService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SchemaContextProvider schemaContextProvider() {
|
||||
return schemaContextProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceConfigSynchronizationProviderService providerService() {
|
||||
return providerService;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,295 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.d.config.sync.impl.netconf;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.util.concurrent.CompletableFuture.completedFuture;
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import org.onlab.util.XmlString;
|
||||
import org.onosproject.d.config.ResourceIds;
|
||||
import org.onosproject.d.config.sync.DeviceConfigSynchronizationProvider;
|
||||
import org.onosproject.d.config.sync.impl.netconf.NetconfDeviceConfigSynchronizerComponent.NetconfContext;
|
||||
import org.onosproject.d.config.sync.operation.SetRequest;
|
||||
import org.onosproject.d.config.sync.operation.SetRequest.Change;
|
||||
import org.onosproject.d.config.sync.operation.SetRequest.Change.Operation;
|
||||
import org.onosproject.d.config.sync.operation.SetResponse;
|
||||
import org.onosproject.d.config.sync.operation.SetResponse.Code;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.net.provider.AbstractProvider;
|
||||
import org.onosproject.net.provider.ProviderId;
|
||||
import org.onosproject.netconf.NetconfDevice;
|
||||
import org.onosproject.netconf.NetconfException;
|
||||
import org.onosproject.netconf.NetconfSession;
|
||||
import org.onosproject.yang.model.DataNode;
|
||||
import org.onosproject.yang.model.DefaultResourceData;
|
||||
import org.onosproject.yang.model.InnerNode;
|
||||
import org.onosproject.yang.model.ResourceData;
|
||||
import org.onosproject.yang.model.ResourceId;
|
||||
import org.onosproject.yang.runtime.AnnotatedNodeInfo;
|
||||
import org.onosproject.yang.runtime.Annotation;
|
||||
import org.onosproject.yang.runtime.CompositeData;
|
||||
import org.onosproject.yang.runtime.CompositeStream;
|
||||
import org.onosproject.yang.runtime.DefaultAnnotatedNodeInfo;
|
||||
import org.onosproject.yang.runtime.DefaultAnnotation;
|
||||
import org.onosproject.yang.runtime.DefaultCompositeData;
|
||||
import org.onosproject.yang.runtime.DefaultRuntimeContext;
|
||||
import org.onosproject.yang.runtime.RuntimeContext;
|
||||
import org.slf4j.Logger;
|
||||
import com.google.common.io.CharStreams;
|
||||
|
||||
/**
|
||||
* Dynamic config synchronizer provider for NETCONF.
|
||||
*
|
||||
* <ul>
|
||||
* <li> Converts POJO YANG into XML.
|
||||
* <li> Adds NETCONF envelope around it.
|
||||
* <li> Send request down to the device over NETCONF
|
||||
* </ul>
|
||||
*/
|
||||
public class NetconfDeviceConfigSynchronizerProvider
|
||||
extends AbstractProvider
|
||||
implements DeviceConfigSynchronizationProvider {
|
||||
|
||||
private static final Logger log = getLogger(NetconfDeviceConfigSynchronizerProvider.class);
|
||||
|
||||
// TODO this should probably be defined on YRT Serializer side
|
||||
/**
|
||||
* {@link RuntimeContext} parameter Dataformat specifying XML.
|
||||
*/
|
||||
private static final String DATAFORMAT_XML = "xml";
|
||||
|
||||
private static final String XMLNS_XC = "xmlns:xc";
|
||||
private static final String NETCONF_1_0_BASE_NAMESPACE =
|
||||
"urn:ietf:params:xml:ns:netconf:base:1.0";
|
||||
|
||||
/**
|
||||
* Annotation to add xc namespace declaration.
|
||||
* {@value #XMLNS_XC}={@value #NETCONF_1_0_BASE_NAMESPACE}
|
||||
*/
|
||||
private static final DefaultAnnotation XMLNS_XC_ANNOTATION =
|
||||
new DefaultAnnotation(XMLNS_XC, NETCONF_1_0_BASE_NAMESPACE);
|
||||
|
||||
private static final String XC_OPERATION = "xc:operation";
|
||||
|
||||
|
||||
private NetconfContext context;
|
||||
|
||||
protected NetconfDeviceConfigSynchronizerProvider(ProviderId id,
|
||||
NetconfContext context) {
|
||||
super(id);
|
||||
this.context = checkNotNull(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<SetResponse> setConfiguration(DeviceId deviceId,
|
||||
SetRequest request) {
|
||||
// sanity check and handle empty change?
|
||||
|
||||
// TODOs:
|
||||
// - Construct convert request object into XML
|
||||
// -- [FutureWork] may need to introduce behaviour for Device specific
|
||||
// workaround insertion
|
||||
|
||||
StringBuilder rpc = new StringBuilder();
|
||||
|
||||
// - Add NETCONF envelope
|
||||
rpc.append("<rpc xmlns=\"").append(NETCONF_1_0_BASE_NAMESPACE).append('"')
|
||||
.append(">");
|
||||
|
||||
rpc.append("<edit-config>");
|
||||
rpc.append("<target>");
|
||||
// TODO directly writing to running for now
|
||||
rpc.append("<running/>");
|
||||
rpc.append("</target>\n");
|
||||
rpc.append("<config ")
|
||||
.append(XMLNS_XC).append("=\"").append(NETCONF_1_0_BASE_NAMESPACE).append("\">");
|
||||
// TODO netconf SBI should probably be adding these envelopes once
|
||||
// netconf SBI is in better shape
|
||||
// TODO In such case netconf sbi need to define namespace externally visible.
|
||||
// ("xc" in above instance)
|
||||
// to be used to add operations on config tree nodes
|
||||
|
||||
|
||||
// Convert change(s) into a DataNode tree
|
||||
for (Change change : request.changes()) {
|
||||
log.trace("change={}", change);
|
||||
|
||||
// TODO switch statement can probably be removed
|
||||
switch (change.op()) {
|
||||
case REPLACE:
|
||||
case UPDATE:
|
||||
case DELETE:
|
||||
// convert DataNode -> ResourceData
|
||||
ResourceData data = toResourceData(change);
|
||||
|
||||
// build CompositeData
|
||||
DefaultCompositeData.Builder compositeData =
|
||||
DefaultCompositeData.builder();
|
||||
|
||||
// add ResourceData
|
||||
compositeData.resourceData(data);
|
||||
|
||||
// add AnnotatedNodeInfo operation
|
||||
compositeData.addAnnotatedNodeInfo(toAnnotatedNodeInfo(change.op(), change.path()));
|
||||
|
||||
RuntimeContext yrtContext = new DefaultRuntimeContext.Builder()
|
||||
.setDataFormat(DATAFORMAT_XML)
|
||||
.addAnnotation(XMLNS_XC_ANNOTATION)
|
||||
.build();
|
||||
CompositeData cdata = compositeData.build();
|
||||
log.trace("CompositeData:{}", cdata);
|
||||
CompositeStream xml = context.yangRuntime().encode(cdata,
|
||||
yrtContext);
|
||||
try {
|
||||
CharStreams.copy(new InputStreamReader(xml.resourceData(), UTF_8), rpc);
|
||||
} catch (IOException e) {
|
||||
log.error("IOException thrown", e);
|
||||
// FIXME handle error
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
log.error("Should never reach here. {}", change);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// - close NETCONF envelope
|
||||
// TODO eventually these should be handled by NETCONF SBI side
|
||||
rpc.append('\n');
|
||||
rpc.append("</config>");
|
||||
rpc.append("</edit-config>");
|
||||
rpc.append("</rpc>");
|
||||
|
||||
// - send requests down to the device
|
||||
NetconfSession session = getNetconfSession(deviceId);
|
||||
if (session == null) {
|
||||
log.error("No session available for {}", deviceId);
|
||||
return completedFuture(SetResponse.response(request,
|
||||
Code.FAILED_PRECONDITION,
|
||||
"No session for " + deviceId));
|
||||
}
|
||||
try {
|
||||
// FIXME Netconf async API is currently screwed up, need to fix
|
||||
// NetconfSession, etc.
|
||||
CompletableFuture<String> response = session.rpc(rpc.toString());
|
||||
log.trace("raw request:\n{}", rpc);
|
||||
log.trace("prettified request:\n{}", XmlString.prettifyXml(rpc));
|
||||
return response.handle((resp, err) -> {
|
||||
if (err == null) {
|
||||
log.trace("reply:\n{}", XmlString.prettifyXml(resp));
|
||||
// FIXME check response properly
|
||||
return SetResponse.ok(request);
|
||||
} else {
|
||||
return SetResponse.response(request, Code.UNKNOWN, err.getMessage());
|
||||
}
|
||||
});
|
||||
} catch (NetconfException e) {
|
||||
// TODO Handle error
|
||||
log.error("NetconfException thrown", e);
|
||||
return completedFuture(SetResponse.response(request, Code.UNKNOWN, e.getMessage()));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// overridable for ease of testing
|
||||
/**
|
||||
* Returns a session for the specified deviceId.
|
||||
*
|
||||
* @param deviceId for which we wish to retrieve a session
|
||||
* @return a NetconfSession with the specified node
|
||||
* or null if this node does not have the session to the specified Device.
|
||||
*/
|
||||
protected NetconfSession getNetconfSession(DeviceId deviceId) {
|
||||
NetconfDevice device = context.netconfController().getNetconfDevice(deviceId);
|
||||
checkNotNull(device, "The specified deviceId could not be found by the NETCONF controller.");
|
||||
NetconfSession session = device.getSession();
|
||||
checkNotNull(session, "A session could not be retrieved for the specified deviceId.");
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates AnnotatedNodeInfo for {@code node}.
|
||||
*
|
||||
* @param op operation
|
||||
* @param parent resourceId
|
||||
* @param node the node
|
||||
* @return AnnotatedNodeInfo
|
||||
*/
|
||||
static AnnotatedNodeInfo annotatedNodeInfo(Operation op,
|
||||
ResourceId parent,
|
||||
DataNode node) {
|
||||
return DefaultAnnotatedNodeInfo.builder()
|
||||
.resourceId(ResourceIds.resourceId(parent, node))
|
||||
.addAnnotation(toAnnotation(op))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates AnnotatedNodeInfo for specified resource path.
|
||||
*
|
||||
* @param op operation
|
||||
* @param path resourceId
|
||||
* @return AnnotatedNodeInfo
|
||||
*/
|
||||
static AnnotatedNodeInfo toAnnotatedNodeInfo(Operation op,
|
||||
ResourceId path) {
|
||||
return DefaultAnnotatedNodeInfo.builder()
|
||||
.resourceId(path)
|
||||
.addAnnotation(toAnnotation(op))
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform DataNode into a ResourceData.
|
||||
*
|
||||
* @param change object
|
||||
* @return ResourceData
|
||||
*/
|
||||
static ResourceData toResourceData(Change change) {
|
||||
DefaultResourceData.Builder builder = DefaultResourceData.builder();
|
||||
builder.resourceId(change.path());
|
||||
if (change.op() != Change.Operation.DELETE) {
|
||||
DataNode dataNode = change.val();
|
||||
if (dataNode instanceof InnerNode) {
|
||||
((InnerNode) dataNode).childNodes().values().forEach(builder::addDataNode);
|
||||
} else {
|
||||
log.error("Unexpected DataNode encountered", change);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
static Annotation toAnnotation(Operation op) {
|
||||
switch (op) {
|
||||
case DELETE:
|
||||
return new DefaultAnnotation(XC_OPERATION, "remove");
|
||||
case REPLACE:
|
||||
return new DefaultAnnotation(XC_OPERATION, "replace");
|
||||
case UPDATE:
|
||||
return new DefaultAnnotation(XC_OPERATION, "merge");
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown operation " + op);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implementation of NETCONF dynamic config synchronizer provider.
|
||||
*/
|
||||
package org.onosproject.d.config.sync.impl.netconf;
|
@ -1,379 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.d.config.sync.impl.netconf;
|
||||
|
||||
import static org.hamcrest.Matchers.hasItem;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||
import static org.junit.Assert.*;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.io.input.ReaderInputStream;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.onlab.util.XmlString;
|
||||
import org.onosproject.d.config.sync.DeviceConfigSynchronizationProviderService;
|
||||
import org.onosproject.d.config.sync.impl.netconf.NetconfDeviceConfigSynchronizerComponent.NetconfContext;
|
||||
import org.onosproject.d.config.sync.operation.SetRequest;
|
||||
import org.onosproject.d.config.sync.operation.SetResponse;
|
||||
import org.onosproject.d.config.sync.operation.SetResponse.Code;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.net.provider.ProviderId;
|
||||
import org.onosproject.netconf.NetconfController;
|
||||
import org.onosproject.netconf.NetconfException;
|
||||
import org.onosproject.netconf.NetconfSession;
|
||||
import org.onosproject.netconf.NetconfSessionAdapter;
|
||||
import org.onosproject.yang.model.DataNode;
|
||||
import org.onosproject.yang.model.DataNode.Type;
|
||||
import org.onosproject.yang.model.InnerNode;
|
||||
import org.onosproject.yang.model.LeafNode;
|
||||
import org.onosproject.yang.model.ResourceData;
|
||||
import org.onosproject.yang.model.ResourceId;
|
||||
import org.onosproject.yang.model.SchemaContextProvider;
|
||||
import org.onosproject.yang.runtime.AnnotatedNodeInfo;
|
||||
import org.onosproject.yang.runtime.CompositeData;
|
||||
import org.onosproject.yang.runtime.CompositeStream;
|
||||
import org.onosproject.yang.runtime.DefaultAnnotatedNodeInfo;
|
||||
import org.onosproject.yang.runtime.DefaultAnnotation;
|
||||
import org.onosproject.yang.runtime.DefaultCompositeStream;
|
||||
import org.onosproject.yang.runtime.RuntimeContext;
|
||||
import org.onosproject.yang.runtime.YangRuntimeService;
|
||||
import com.google.common.io.CharSource;
|
||||
|
||||
public class NetconfDeviceConfigSynchronizerProviderTest {
|
||||
|
||||
private static final ProviderId PID = new ProviderId("netconf", "test");
|
||||
private static final DeviceId DID = DeviceId.deviceId("netconf:testDevice");
|
||||
|
||||
private static final String XMLNS_XC = "xmlns:xc";
|
||||
private static final String NETCONF_1_0_BASE_NAMESPACE =
|
||||
"urn:ietf:params:xml:ns:netconf:base:1.0";
|
||||
|
||||
private static final DefaultAnnotation XC_ANNOTATION =
|
||||
new DefaultAnnotation(XMLNS_XC, NETCONF_1_0_BASE_NAMESPACE);
|
||||
|
||||
private static final DefaultAnnotation AN_XC_REPLACE_OPERATION =
|
||||
new DefaultAnnotation("xc:operation", "replace");
|
||||
|
||||
private static final DefaultAnnotation AN_XC_REMOVE_OPERATION =
|
||||
new DefaultAnnotation("xc:operation", "remove");
|
||||
|
||||
/**
|
||||
* Yang namespace for test config data.
|
||||
*/
|
||||
private static final String TEST_NS = "testNS";
|
||||
|
||||
private static final ResourceId RID_INTERFACES =
|
||||
ResourceId.builder().addBranchPointSchema("interfaces", TEST_NS).build();
|
||||
|
||||
private NetconfDeviceConfigSynchronizerProvider sut;
|
||||
|
||||
private NetconfContext ncCtx;
|
||||
|
||||
|
||||
// Set following accordingly to suite test scenario
|
||||
NetconfSession testNcSession;
|
||||
YangRuntimeService testYangRuntime;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
ncCtx = new TestNetconfContext();
|
||||
|
||||
sut = new NetconfDeviceConfigSynchronizerProvider(PID, ncCtx) {
|
||||
// overriding to avoid mocking whole NetconController and all that.
|
||||
@Override
|
||||
protected NetconfSession getNetconfSession(DeviceId deviceId) {
|
||||
assertEquals(DID, deviceId);
|
||||
return testNcSession;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceOperation() throws Exception {
|
||||
// plug drivers with assertions
|
||||
testYangRuntime = onEncode((data, context) -> {
|
||||
assertEquals("xml", context.getDataFormat());
|
||||
assertThat(context.getProtocolAnnotations(), hasItem(XC_ANNOTATION));
|
||||
|
||||
// assert CompositeData
|
||||
ResourceData rData = data.resourceData();
|
||||
List<AnnotatedNodeInfo> infos = data.annotatedNodesInfo();
|
||||
|
||||
ResourceId interfacesRid = RID_INTERFACES;
|
||||
AnnotatedNodeInfo intfsAnnot = DefaultAnnotatedNodeInfo.builder()
|
||||
.resourceId(interfacesRid)
|
||||
.addAnnotation(AN_XC_REPLACE_OPERATION)
|
||||
.build();
|
||||
assertThat("interfaces has replace operation", infos, hasItem(intfsAnnot));
|
||||
|
||||
// assertion for ResourceData.
|
||||
assertEquals(RID_INTERFACES, rData.resourceId());
|
||||
assertThat("has 1 child", rData.dataNodes(), hasSize(1));
|
||||
assertThat("which is interface",
|
||||
rData.dataNodes().get(0).key().schemaId().name(),
|
||||
is("interface"));
|
||||
// todo: assert the rest of the tree if it make sense.
|
||||
|
||||
// FIXME it's unclear what URI is expected here
|
||||
String id = URI.create("netconf:testDevice").toString();
|
||||
|
||||
String inXml = deviceConfigAsXml("replace");
|
||||
|
||||
return toCompositeStream(id, inXml);
|
||||
});
|
||||
testNcSession = new TestEditNetconfSession();
|
||||
|
||||
|
||||
// building test data
|
||||
ResourceId interfacesId = RID_INTERFACES;
|
||||
DataNode interfaces = deviceConfigNode();
|
||||
SetRequest request = SetRequest.builder()
|
||||
.replace(interfacesId, interfaces)
|
||||
.build();
|
||||
|
||||
// test start
|
||||
CompletableFuture<SetResponse> f = sut.setConfiguration(DID, request);
|
||||
SetResponse response = f.get(5, TimeUnit.MINUTES);
|
||||
|
||||
assertEquals(Code.OK, response.code());
|
||||
assertEquals(request.subjects(), response.subjects());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDeleteOperation() throws Exception {
|
||||
// plug drivers with assertions
|
||||
testYangRuntime = onEncode((data, context) -> {
|
||||
assertEquals("xml", context.getDataFormat());
|
||||
assertThat(context.getProtocolAnnotations(), hasItem(XC_ANNOTATION));
|
||||
|
||||
// assert CompositeData
|
||||
ResourceData rData = data.resourceData();
|
||||
List<AnnotatedNodeInfo> infos = data.annotatedNodesInfo();
|
||||
|
||||
ResourceId interfacesRid = RID_INTERFACES;
|
||||
AnnotatedNodeInfo intfsAnnot = DefaultAnnotatedNodeInfo.builder()
|
||||
.resourceId(interfacesRid)
|
||||
.addAnnotation(AN_XC_REMOVE_OPERATION)
|
||||
.build();
|
||||
assertThat("interfaces has replace operation", infos, hasItem(intfsAnnot));
|
||||
|
||||
// assertion for ResourceData.
|
||||
assertEquals(RID_INTERFACES, rData.resourceId());
|
||||
assertThat("has no child", rData.dataNodes(), hasSize(0));
|
||||
|
||||
// FIXME it's unclear what URI is expected here
|
||||
String id = URI.create("netconf:testDevice").toString();
|
||||
|
||||
String inXml = deviceConfigAsXml("remove");
|
||||
|
||||
return toCompositeStream(id, inXml);
|
||||
});
|
||||
testNcSession = new TestEditNetconfSession();
|
||||
|
||||
// building test data
|
||||
ResourceId interfacesId = RID_INTERFACES;
|
||||
SetRequest request = SetRequest.builder()
|
||||
.delete(interfacesId)
|
||||
.build();
|
||||
|
||||
// test start
|
||||
CompletableFuture<SetResponse> f = sut.setConfiguration(DID, request);
|
||||
|
||||
SetResponse response = f.get(5, TimeUnit.MINUTES);
|
||||
assertEquals(Code.OK, response.code());
|
||||
assertEquals(request.subjects(), response.subjects());
|
||||
}
|
||||
|
||||
/**
|
||||
* DataNode for testing.
|
||||
*
|
||||
* <pre>
|
||||
* +-interfaces
|
||||
* |
|
||||
* +- interface{intf-name="en0"}
|
||||
* |
|
||||
* +- speed = "10G"
|
||||
* +- state = "up"
|
||||
*
|
||||
* </pre>
|
||||
* @return DataNode
|
||||
*/
|
||||
private DataNode deviceConfigNode() {
|
||||
InnerNode.Builder intfs = InnerNode.builder("interfaces", TEST_NS);
|
||||
intfs.type(Type.SINGLE_INSTANCE_NODE);
|
||||
InnerNode.Builder intf = intfs.createChildBuilder("interface", TEST_NS);
|
||||
intf.type(Type.SINGLE_INSTANCE_LEAF_VALUE_NODE);
|
||||
intf.addKeyLeaf("name", TEST_NS, "Ethernet0/0");
|
||||
LeafNode.Builder speed = intf.createChildBuilder("mtu", TEST_NS, "1500");
|
||||
speed.type(Type.SINGLE_INSTANCE_LEAF_VALUE_NODE);
|
||||
|
||||
intf.addNode(speed.build());
|
||||
intfs.addNode(intf.build());
|
||||
return intfs.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link #deviceConfigNode()} as XML.
|
||||
*
|
||||
* @param operation xc:operation value on {@code interfaces} node
|
||||
* @return XML
|
||||
*/
|
||||
private String deviceConfigAsXml(String operation) {
|
||||
return "<interfaces xmlns=\"http://example.com/schema/1.2/config\""
|
||||
+ " xc:operation=\"" + operation + "\">\n" +
|
||||
" <interface>\n" +
|
||||
" <name>Ethernet0/0</name>\n" +
|
||||
" <mtu>1500</mtu>\n" +
|
||||
" </interface>\n" +
|
||||
"</interfaces>";
|
||||
}
|
||||
|
||||
private String rpcReplyOk(int messageid) {
|
||||
return "<rpc-reply message-id=\"" + messageid + "\"\n" +
|
||||
" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n" +
|
||||
" <ok/>\n" +
|
||||
"</rpc-reply>";
|
||||
}
|
||||
|
||||
private int fetchMessageId(String request) {
|
||||
int messageid;
|
||||
Pattern msgId = Pattern.compile("message-id=['\"]([0-9]+)['\"]");
|
||||
Matcher matcher = msgId.matcher(request);
|
||||
if (matcher.find()) {
|
||||
messageid = Integer.parseInt(matcher.group(1));
|
||||
} else {
|
||||
messageid = -1;
|
||||
}
|
||||
return messageid;
|
||||
}
|
||||
|
||||
|
||||
protected CompositeStream toCompositeStream(String id, String inXml) {
|
||||
try {
|
||||
InputStream xml = new ReaderInputStream(
|
||||
CharSource.wrap(inXml)
|
||||
.openStream());
|
||||
|
||||
return new DefaultCompositeStream(id, xml);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that it received edit-config message and reply Ok.
|
||||
*/
|
||||
private class TestEditNetconfSession extends NetconfSessionAdapter {
|
||||
@Override
|
||||
public CompletableFuture<String> rpc(String request)
|
||||
throws NetconfException {
|
||||
System.out.println("TestEditNetconfSession received:");
|
||||
System.out.println(XmlString.prettifyXml(request));
|
||||
|
||||
// Extremely naive request rpc message check
|
||||
assertThat(request, stringContainsInOrder(Arrays.asList(
|
||||
"<rpc",
|
||||
"<edit-config",
|
||||
"<target",
|
||||
"<config",
|
||||
|
||||
"</config>",
|
||||
"</edit-config>",
|
||||
"</rpc>")));
|
||||
|
||||
assertThat("XML namespace decl exists",
|
||||
request, Matchers.containsString("xmlns:xc"));
|
||||
|
||||
assertThat("netconf operation exists",
|
||||
request, Matchers.containsString("xc:operation"));
|
||||
|
||||
return CompletableFuture.completedFuture(rpcReplyOk(fetchMessageId(request)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates mock YangRuntimeService.
|
||||
*
|
||||
* @param body to execute when {@link YangRuntimeService#encode(CompositeData, RuntimeContext)} was called.
|
||||
* @return YangRuntimeService instance
|
||||
*/
|
||||
TestYangRuntimeService onEncode(BiFunction<CompositeData, RuntimeContext, CompositeStream> body) {
|
||||
return new TestYangRuntimeService() {
|
||||
@Override
|
||||
public CompositeStream encode(CompositeData internal,
|
||||
RuntimeContext context) {
|
||||
return body.apply(internal, context);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private abstract class TestYangRuntimeService implements YangRuntimeService {
|
||||
|
||||
@Override
|
||||
public CompositeStream encode(CompositeData internal,
|
||||
RuntimeContext context) {
|
||||
fail("stub not implemented");
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public CompositeData decode(CompositeStream external,
|
||||
RuntimeContext context) {
|
||||
fail("stub not implemented");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private final class TestNetconfContext implements NetconfContext {
|
||||
@Override
|
||||
public DeviceConfigSynchronizationProviderService providerService() {
|
||||
fail("Add stub driver as necessary");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SchemaContextProvider schemaContextProvider() {
|
||||
fail("Add stub driver as necessary");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public YangRuntimeService yangRuntime() {
|
||||
return testYangRuntime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetconfController netconfController() {
|
||||
fail("Add stub driver as necessary");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
APPS = [
|
||||
# dynamic config
|
||||
"org.onosproject.config",
|
||||
]
|
||||
|
||||
COMPILE_DEPS = CORE_DEPS + ONOS_YANG + [
|
||||
"//apps/config:onos-apps-config",
|
||||
]
|
||||
|
||||
osgi_jar_with_tests(
|
||||
deps = COMPILE_DEPS,
|
||||
)
|
||||
|
||||
onos_app(
|
||||
category = "Utility",
|
||||
description = "Application to support the Dynamic configuration service.",
|
||||
required_apps = APPS,
|
||||
title = "Dynamic Configuration Synchronizer",
|
||||
url = "http://onosproject.org",
|
||||
)
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.d.config.sync;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.onosproject.d.config.sync.operation.SetRequest;
|
||||
import org.onosproject.d.config.sync.operation.SetResponse;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.net.provider.Provider;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
|
||||
// TODO might want to remove Device~ prefix, class name too long.
|
||||
/**
|
||||
* Abstraction of a device config synchronization provider.
|
||||
* <p>
|
||||
* Provides a mean for propagating dynamic config triggered change down to
|
||||
* the device.
|
||||
*/
|
||||
@Beta
|
||||
public interface DeviceConfigSynchronizationProvider extends Provider {
|
||||
|
||||
// TODO API to propagate dynamic config subsystem side change down to the
|
||||
// device
|
||||
|
||||
/**
|
||||
* Requests a device to set configuration as specified.
|
||||
*
|
||||
* @param deviceId target Device identifier
|
||||
* @param request configuration requests
|
||||
* @return result
|
||||
*/
|
||||
CompletableFuture<SetResponse> setConfiguration(DeviceId deviceId, SetRequest request);
|
||||
|
||||
// TODO API for Get from Device
|
||||
// CompletableFuture<GetResponse> getConfiguration(DeviceId deviceId, GetRequest request);
|
||||
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.d.config.sync;
|
||||
|
||||
import org.onosproject.net.provider.ProviderRegistry;
|
||||
|
||||
/**
|
||||
* Abstraction of a device config synchronization provider registry.
|
||||
*/
|
||||
public interface DeviceConfigSynchronizationProviderRegistry
|
||||
extends ProviderRegistry<DeviceConfigSynchronizationProvider,
|
||||
DeviceConfigSynchronizationProviderService> {
|
||||
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.d.config.sync;
|
||||
|
||||
import org.onosproject.net.provider.ProviderService;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
|
||||
/**
|
||||
* Service which configuration synchronization provider can interact
|
||||
* with the service.
|
||||
* <p>
|
||||
* Provides a mean to propagate device triggered change event upward to
|
||||
* dynamic config subsystem.
|
||||
*/
|
||||
@Beta
|
||||
public interface DeviceConfigSynchronizationProviderService
|
||||
extends ProviderService<DeviceConfigSynchronizationProvider> {
|
||||
|
||||
// TODO API to propagate device detected change upwards
|
||||
// e.g., in reaction to NETCONF async notification,
|
||||
// report polling result up to DynConfig subsystem
|
||||
}
|
@ -1,397 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.d.config.sync.impl;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.onlab.util.Tools;
|
||||
import org.onosproject.config.DynamicConfigEvent;
|
||||
import org.onosproject.config.DynamicConfigEvent.Type;
|
||||
import org.onosproject.config.DynamicConfigListener;
|
||||
import org.onosproject.config.DynamicConfigService;
|
||||
import org.onosproject.config.Filter;
|
||||
import org.onosproject.d.config.DataNodes;
|
||||
import org.onosproject.d.config.DeviceResourceIds;
|
||||
import org.onosproject.d.config.ResourceIds;
|
||||
import org.onosproject.d.config.sync.DeviceConfigSynchronizationProvider;
|
||||
import org.onosproject.d.config.sync.DeviceConfigSynchronizationProviderRegistry;
|
||||
import org.onosproject.d.config.sync.DeviceConfigSynchronizationProviderService;
|
||||
import org.onosproject.d.config.sync.operation.SetRequest;
|
||||
import org.onosproject.d.config.sync.operation.SetResponse;
|
||||
import org.onosproject.d.config.sync.operation.SetResponse.Code;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.net.config.NetworkConfigService;
|
||||
import org.onosproject.net.provider.AbstractProviderRegistry;
|
||||
import org.onosproject.net.provider.AbstractProviderService;
|
||||
import org.onosproject.store.primitives.TransactionId;
|
||||
import org.onosproject.yang.model.DataNode;
|
||||
import org.onosproject.yang.model.ResourceId;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Deactivate;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.concurrent.CompletableFuture.completedFuture;
|
||||
import static org.onosproject.d.config.DeviceResourceIds.isUnderDeviceRootNode;
|
||||
import static org.onosproject.d.config.DeviceResourceIds.toDeviceId;
|
||||
import static org.onosproject.d.config.DeviceResourceIds.toResourceId;
|
||||
import static org.onosproject.d.config.sync.operation.SetResponse.response;
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
/**
|
||||
* Component to bridge Dynamic Config store and the Device configuration state.
|
||||
*
|
||||
* <ul>
|
||||
* <li> Propagate DynamicConfig service change downward to Device side via provider.
|
||||
* <li> Propagate Device triggered change event upward to DyamicConfig service.
|
||||
* </ul>
|
||||
*/
|
||||
@Beta
|
||||
@Component(immediate = true, service = DeviceConfigSynchronizationProviderRegistry.class)
|
||||
public class DynamicDeviceConfigSynchronizer
|
||||
extends AbstractProviderRegistry<DeviceConfigSynchronizationProvider,
|
||||
DeviceConfigSynchronizationProviderService>
|
||||
implements DeviceConfigSynchronizationProviderRegistry {
|
||||
|
||||
private static final Logger log = getLogger(DynamicDeviceConfigSynchronizer.class);
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected DynamicConfigService dynConfigService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected NetworkConfigService netcfgService;
|
||||
|
||||
private DynamicConfigListener listener = new InnerDyConListener();
|
||||
|
||||
// FIXME hack for unconsolidated event bug
|
||||
private Duration quietPeriod = Duration.ofSeconds(2);
|
||||
private long quietUntil = 0;
|
||||
|
||||
@Activate
|
||||
public void activate() {
|
||||
// TODO start background task to sync Controller and Device?
|
||||
dynConfigService.addListener(listener);
|
||||
log.info("Started");
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
public void deactivate() {
|
||||
dynConfigService.removeListener(listener);
|
||||
log.info("Stopped");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected DeviceConfigSynchronizationProviderService createProviderService(
|
||||
DeviceConfigSynchronizationProvider provider) {
|
||||
return new InternalConfigSynchronizationServiceProvider(provider);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DeviceConfigSynchronizationProvider defaultProvider() {
|
||||
// TODO return provider instance which can deal with "general" provider?
|
||||
return super.defaultProvider();
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy to relay Device change event for propagating running "state"
|
||||
* information up to dynamic configuration service.
|
||||
*/
|
||||
class InternalConfigSynchronizationServiceProvider
|
||||
extends AbstractProviderService<DeviceConfigSynchronizationProvider>
|
||||
implements DeviceConfigSynchronizationProviderService {
|
||||
|
||||
protected InternalConfigSynchronizationServiceProvider(DeviceConfigSynchronizationProvider provider) {
|
||||
super(provider);
|
||||
}
|
||||
|
||||
// TODO API for passive information propagation to be added later on
|
||||
}
|
||||
|
||||
/**
|
||||
* DynamicConfigListener to trigger active synchronization toward the device.
|
||||
*/
|
||||
class InnerDyConListener implements DynamicConfigListener {
|
||||
|
||||
@Override
|
||||
public boolean isRelevant(DynamicConfigEvent event) {
|
||||
// TODO NetconfActiveComponent.isRelevant(DynamicConfigEvent)
|
||||
// seems to be doing some filtering
|
||||
// Logic filtering for L3VPN is probably a demo hack,
|
||||
// but is there any portion of it which is really needed?
|
||||
// e.g., listen only for device tree events?
|
||||
|
||||
ResourceId path = event.subject();
|
||||
// TODO only device tree related event is relevant.
|
||||
// 1) path is under device tree
|
||||
// 2) path is root, and DataNode contains element under node
|
||||
// ...
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void event(DynamicConfigEvent event) {
|
||||
// Note: removed accumulator in the old code assuming,
|
||||
// event accumulation will happen on Device Config Event level.
|
||||
|
||||
// TODO execute off event dispatch thread
|
||||
processEventNonBatch(event);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void processEventNonBatch(DynamicConfigEvent event) {
|
||||
if (System.currentTimeMillis() < quietUntil) {
|
||||
log.trace("Ignoring {}. Quiet period until {}",
|
||||
event, Tools.defaultOffsetDataTime(quietUntil));
|
||||
return;
|
||||
}
|
||||
|
||||
ResourceId path = event.subject();
|
||||
if (isUnderDeviceRootNode(path)) {
|
||||
log.trace("processing event:{}", event);
|
||||
|
||||
DeviceId deviceId = DeviceResourceIds.toDeviceId(path);
|
||||
ResourceId deviceRootPath = DeviceResourceIds.toResourceId(deviceId);
|
||||
|
||||
ResourceId absPath = ResourceIds.concat(ResourceIds.ROOT_ID, path);
|
||||
ResourceId relPath = ResourceIds.relativize(deviceRootPath, absPath);
|
||||
// give me everything Filter
|
||||
Filter giveMeEverything = Filter.builder().build();
|
||||
|
||||
DataNode node = dynConfigService.readNode(path, giveMeEverything);
|
||||
SetRequest request;
|
||||
switch (event.type()) {
|
||||
|
||||
case NODE_ADDED:
|
||||
case NODE_REPLACED:
|
||||
request = SetRequest.builder().replace(relPath, node).build();
|
||||
break;
|
||||
case NODE_UPDATED:
|
||||
// Event has no pay load, only thing we can do is replace.
|
||||
request = SetRequest.builder().replace(relPath, node).build();
|
||||
break;
|
||||
case NODE_DELETED:
|
||||
request = SetRequest.builder().delete(relPath).build();
|
||||
break;
|
||||
case UNKNOWN_OPRN:
|
||||
default:
|
||||
log.error("Unexpected event {}, aborting", event);
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("Dispatching {} request {}", deviceId, request);
|
||||
CompletableFuture<SetResponse> response = dispatchRequest(deviceId, request);
|
||||
response.whenComplete((resp, e) -> {
|
||||
if (e == null) {
|
||||
if (resp.code() == Code.OK) {
|
||||
log.info("{} for {} complete", resp, deviceId);
|
||||
} else {
|
||||
log.warn("{} for {} had problem", resp, deviceId);
|
||||
}
|
||||
} else {
|
||||
log.error("Request to {} failed {}", deviceId, response, e);
|
||||
}
|
||||
});
|
||||
|
||||
// FIXME hack for unconsolidated event bug
|
||||
quietUntil = System.currentTimeMillis() + quietPeriod.toMillis();
|
||||
} else {
|
||||
log.debug("Ignored event's ResourceId: {}", event.subject());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// was sketch to handle case, where event could contain batch of things...
|
||||
private void processEvent(DynamicConfigEvent event) {
|
||||
// TODO assuming event object will contain batch of (atomic) change event
|
||||
|
||||
// What the new event will contain:
|
||||
Type evtType = event.type();
|
||||
|
||||
// Transaction ID, can be null
|
||||
TransactionId txId = null;
|
||||
|
||||
// TODO this might change into collection of (path, val_before, val_after)
|
||||
|
||||
ResourceId path = event.subject();
|
||||
// data node (can be tree) representing change, it could be incremental update
|
||||
DataNode val = null;
|
||||
|
||||
// build per-Device SetRequest
|
||||
// val could be a tree, containing multiple Device tree,
|
||||
// break them down into per-Device sub-tree
|
||||
Map<DeviceId, SetRequest.Builder> requests = new HashMap<>();
|
||||
|
||||
if (isUnderDeviceRootNode(path)) {
|
||||
// about single device
|
||||
buildDeviceRequest(requests, evtType, path, toDeviceId(path), val);
|
||||
|
||||
} else if (DeviceResourceIds.isRootOrDevicesNode(path)) {
|
||||
// => potentially contain changes spanning multiple Devices
|
||||
Map<DeviceId, DataNode> perDevices = perDevices(path, val);
|
||||
|
||||
perDevices.forEach((did, dataNode) -> {
|
||||
buildDeviceRequest(requests, evtType, toResourceId(did), did, dataNode);
|
||||
});
|
||||
|
||||
// TODO special care is probably required for delete cases
|
||||
// especially delete all under devices
|
||||
|
||||
} else {
|
||||
log.warn("Event not related to a Device?");
|
||||
}
|
||||
|
||||
|
||||
// TODO assuming event is a batch,
|
||||
// potentially containing changes for multiple devices,
|
||||
// who will process/coordinate the batch event?
|
||||
|
||||
|
||||
// TODO loop through per-Device change set
|
||||
List<CompletableFuture<SetResponse>> responses =
|
||||
requests.entrySet().stream()
|
||||
.map(entry -> dispatchRequest(entry.getKey(), entry.getValue().build()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// wait for all responses
|
||||
List<SetResponse> allResults = Tools.allOf(responses).join();
|
||||
// TODO deal with partial failure case (multi-device coordination)
|
||||
log.info("DEBUG: results: {}", allResults);
|
||||
}
|
||||
|
||||
// might make sense to make this public
|
||||
CompletableFuture<SetResponse> dispatchRequest(DeviceId devId, SetRequest req) {
|
||||
|
||||
// determine appropriate provider for this Device
|
||||
DeviceConfigSynchronizationProvider provider = this.getProvider(devId);
|
||||
|
||||
if (provider == null) {
|
||||
// no appropriate provider found
|
||||
// return completed future with failed SetResponse
|
||||
return completedFuture(response(req,
|
||||
SetResponse.Code.FAILED_PRECONDITION,
|
||||
"no provider found for " + devId));
|
||||
}
|
||||
|
||||
// dispatch request
|
||||
return provider.setConfiguration(devId, req)
|
||||
.handle((resp, err) -> {
|
||||
if (err == null) {
|
||||
// set complete
|
||||
log.info("DEBUG: Req:{}, Resp:{}", req, resp);
|
||||
return resp;
|
||||
} else {
|
||||
// fatal error
|
||||
log.error("Fatal error on {}", req, err);
|
||||
return response(req,
|
||||
SetResponse.Code.UNKNOWN,
|
||||
"Unknown error " + err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// may eventually reuse with batch event
|
||||
/**
|
||||
* Build device request about a Device.
|
||||
*
|
||||
* @param requests map containing request builder to populate
|
||||
* @param evtType change request type
|
||||
* @param path to {@code val}
|
||||
* @param did DeviceId which {@code path} is about
|
||||
* @param val changed node to write
|
||||
*/
|
||||
private void buildDeviceRequest(Map<DeviceId, SetRequest.Builder> requests,
|
||||
Type evtType,
|
||||
ResourceId path,
|
||||
DeviceId did,
|
||||
DataNode val) {
|
||||
|
||||
SetRequest.Builder request =
|
||||
requests.computeIfAbsent(did, d -> SetRequest.builder());
|
||||
|
||||
switch (evtType) {
|
||||
case NODE_ADDED:
|
||||
case NODE_REPLACED:
|
||||
request.replace(path, val);
|
||||
break;
|
||||
|
||||
case NODE_UPDATED:
|
||||
// TODO Auto-generated method stub
|
||||
request.update(path, val);
|
||||
break;
|
||||
|
||||
case NODE_DELETED:
|
||||
// TODO Auto-generated method stub
|
||||
request.delete(path);
|
||||
break;
|
||||
|
||||
case UNKNOWN_OPRN:
|
||||
default:
|
||||
log.warn("Ignoring unexpected {}", evtType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Breaks down tree {@code val} into per Device subtree.
|
||||
*
|
||||
* @param path pointing to {@code val}
|
||||
* @param val tree which contains only 1 Device.
|
||||
* @return Device node relative DataNode for each DeviceId
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
private static Map<DeviceId, DataNode> perDevices(ResourceId path, DataNode val) {
|
||||
if (DeviceResourceIds.isUnderDeviceRootNode(path)) {
|
||||
// - if path is device root or it's subtree, path alone is sufficient
|
||||
return ImmutableMap.of(DeviceResourceIds.toDeviceId(path), val);
|
||||
|
||||
} else if (DeviceResourceIds.isRootOrDevicesNode(path)) {
|
||||
// - if path is "/" or devices, it might be constructible from val tree
|
||||
final Collection<DataNode> devicesChildren;
|
||||
if (DeviceResourceIds.isRootNode(path)) {
|
||||
// root
|
||||
devicesChildren = DataNodes.childOnlyByName(val, DeviceResourceIds.DEVICES_NAME)
|
||||
.map(dn -> DataNodes.children(dn))
|
||||
.orElse(ImmutableList.of());
|
||||
} else {
|
||||
// devices
|
||||
devicesChildren = DataNodes.children(val);
|
||||
}
|
||||
|
||||
return devicesChildren.stream()
|
||||
// TODO use full schemaId for filtering when ready
|
||||
.filter(dn -> dn.key().schemaId().name().equals(DeviceResourceIds.DEVICE_NAME))
|
||||
.collect(Collectors.toMap(dn -> DeviceResourceIds.toDeviceId(dn.key()),
|
||||
dn -> dn));
|
||||
|
||||
}
|
||||
throw new IllegalArgumentException(path + " not related to Device");
|
||||
}
|
||||
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
/**
|
||||
* Implementation of dynamic config synchronizer.
|
||||
*/
|
||||
package org.onosproject.d.config.sync.impl;
|
@ -1,240 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.d.config.sync.operation;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.onosproject.d.config.sync.operation.SetRequest.Change.Operation;
|
||||
import org.onosproject.yang.model.DataNode;
|
||||
import org.onosproject.yang.model.ResourceId;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
// One SetRequest is expected to be a transaction, all-or-nothing
|
||||
/**
|
||||
* Collection of changes about a single Device,
|
||||
* intended to be applied to the Device transactionally.
|
||||
*/
|
||||
@Beta
|
||||
public final class SetRequest {
|
||||
|
||||
private final Collection<Change> changes;
|
||||
|
||||
SetRequest(Collection<Change> changes) {
|
||||
this.changes = ImmutableList.copyOf(changes);
|
||||
}
|
||||
|
||||
public Collection<Change> changes() {
|
||||
return changes;
|
||||
}
|
||||
|
||||
public Collection<Pair<Operation, ResourceId>> subjects() {
|
||||
return changes.stream()
|
||||
.map(c -> Pair.of(c.op(), c.path()))
|
||||
.collect(ImmutableList.toImmutableList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof SetRequest) {
|
||||
SetRequest that = (SetRequest) obj;
|
||||
return Objects.equals(this.changes, that.changes);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(changes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(getClass())
|
||||
.add("changes", changes)
|
||||
.toString();
|
||||
}
|
||||
public static SetRequest.Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private final List<Change> changes = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Returns changes contained in this builder.
|
||||
*
|
||||
* @return unmodifiable list view of Changes
|
||||
*/
|
||||
public List<Change> changes() {
|
||||
return Collections.unmodifiableList(changes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds request to remove specified {@code path}.
|
||||
*
|
||||
* @param path resource path relative to device root node
|
||||
* @return self
|
||||
*/
|
||||
public SetRequest.Builder delete(ResourceId path) {
|
||||
changes.add(Change.delete(path));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds request to replace specified {@code path} with specified {@code val}.
|
||||
*
|
||||
* @param path resource path relative to device root node
|
||||
* @param val resource value
|
||||
* @return self
|
||||
*/
|
||||
public SetRequest.Builder replace(ResourceId path, DataNode val) {
|
||||
changes.add(Change.replace(path, val));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds request to update/merge specified {@code val} to the {@code path}.
|
||||
*
|
||||
* @param path resource path relative to device root node
|
||||
* @param val resource value
|
||||
* @return self
|
||||
*/
|
||||
public SetRequest.Builder update(ResourceId path, DataNode val) {
|
||||
changes.add(Change.update(path, val));
|
||||
return this;
|
||||
}
|
||||
|
||||
public SetRequest build() {
|
||||
return new SetRequest(changes);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Change {
|
||||
|
||||
public enum Operation {
|
||||
|
||||
// Note: equivalent to remove in netconf
|
||||
/**
|
||||
* Request to delete specified {@code path}.
|
||||
* If path does not exist, it is silently ignored.
|
||||
*/
|
||||
DELETE,
|
||||
// Note: equivalent to replace in netconf
|
||||
/**
|
||||
* Request to replace specified {@code path} with specified {@code val}.
|
||||
*/
|
||||
REPLACE,
|
||||
// Note: equivalent to merge in netconf
|
||||
/**
|
||||
* Request to update/merge specified {@code val} to the {@code path}.
|
||||
*/
|
||||
UPDATE
|
||||
}
|
||||
|
||||
private final Operation op;
|
||||
private final ResourceId path;
|
||||
private final Optional<DataNode> val;
|
||||
|
||||
public static Change delete(ResourceId path) {
|
||||
return new Change(Operation.DELETE, path, Optional.empty());
|
||||
}
|
||||
|
||||
public static Change replace(ResourceId path, DataNode val) {
|
||||
return new Change(Operation.REPLACE, path, Optional.of(val));
|
||||
}
|
||||
|
||||
public static Change update(ResourceId path, DataNode val) {
|
||||
return new Change(Operation.UPDATE, path, Optional.of(val));
|
||||
}
|
||||
|
||||
Change(Operation op, ResourceId path, Optional<DataNode> val) {
|
||||
this.op = checkNotNull(op);
|
||||
this.path = checkNotNull(path);
|
||||
this.val = checkNotNull(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns type of change operation.
|
||||
*
|
||||
* @return Operation
|
||||
*/
|
||||
public Operation op() {
|
||||
return op;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns resource path to be changed.
|
||||
*
|
||||
* @return resource path relative to device root node
|
||||
*/
|
||||
public ResourceId path() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@code val} specified.
|
||||
*
|
||||
* @return {@code val}
|
||||
* @throws NoSuchElementException if this object represent {@code DELETE} op.
|
||||
*/
|
||||
public DataNode val() {
|
||||
return val.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof Change) {
|
||||
Change that = (Change) obj;
|
||||
return Objects.equals(this.op, that.op) &&
|
||||
Objects.equals(this.path, that.path) &&
|
||||
Objects.equals(this.val, that.val);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(op, path, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(getClass())
|
||||
.add("op", op)
|
||||
.add("path", path)
|
||||
.add("val", val)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,136 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.d.config.sync.operation;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.onosproject.d.config.sync.operation.SetRequest.Change.Operation;
|
||||
import org.onosproject.yang.model.ResourceId;
|
||||
|
||||
import com.google.common.annotations.Beta;
|
||||
import com.google.common.base.MoreObjects;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
|
||||
@Beta
|
||||
public final class SetResponse {
|
||||
|
||||
// partially borrowed from io.grpc.Status.Code,
|
||||
// might want to borrow all of them
|
||||
public enum Code {
|
||||
OK,
|
||||
CANCELLED,
|
||||
|
||||
UNKNOWN,
|
||||
|
||||
INVALID_ARGUMENT,
|
||||
|
||||
NOT_FOUND,
|
||||
ALREADY_EXISTS,
|
||||
|
||||
FAILED_PRECONDITION,
|
||||
ABORTED,
|
||||
UNAVAILABLE,
|
||||
}
|
||||
|
||||
private final Collection<Pair<Operation, ResourceId>> subjects;
|
||||
|
||||
private final SetResponse.Code code;
|
||||
|
||||
// human readable error message for logging purpose
|
||||
private final String message;
|
||||
|
||||
SetResponse(Collection<Pair<Operation, ResourceId>> subjects,
|
||||
SetResponse.Code code,
|
||||
String message) {
|
||||
this.subjects = ImmutableList.copyOf(subjects);
|
||||
this.code = checkNotNull(code);
|
||||
this.message = checkNotNull(message);
|
||||
}
|
||||
|
||||
public Collection<Pair<Operation, ResourceId>> subjects() {
|
||||
return subjects;
|
||||
}
|
||||
|
||||
public Code code() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String message() {
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates SetResponse instance from request.
|
||||
*
|
||||
* @param request original request this response corresponds to
|
||||
* @param code response status code
|
||||
* @param message human readable error message for logging purpose.
|
||||
* can be left empty string on OK response.
|
||||
* @return SetResponse instance
|
||||
*/
|
||||
public static SetResponse response(SetRequest request,
|
||||
Code code,
|
||||
String message) {
|
||||
return new SetResponse(request.subjects(), code, checkNotNull(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates successful SetResponce instance from request.
|
||||
*
|
||||
* @param request original request this response corresponds to
|
||||
* @return SetResponse instance
|
||||
*/
|
||||
public static SetResponse ok(SetRequest request) {
|
||||
return new SetResponse(request.subjects(), Code.OK, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(subjects, code, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof SetResponse) {
|
||||
SetResponse that = (SetResponse) obj;
|
||||
return Objects.equals(this.subjects, that.subjects) &&
|
||||
Objects.equals(this.code, that.code) &&
|
||||
Objects.equals(this.message, that.message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper(getClass())
|
||||
.add("code", code)
|
||||
.add("subjects", subjects)
|
||||
.add("message", message)
|
||||
.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
/**
|
||||
* Dynamic config synchronizer API related value objects.
|
||||
*/
|
||||
package org.onosproject.d.config.sync.operation;
|
@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
/**
|
||||
* Dynamic config synchronizer API.
|
||||
*/
|
||||
package org.onosproject.d.config.sync;
|
@ -1,183 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.d.config.sync.impl;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.onosproject.d.config.ResourceIds.ROOT_ID;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.onosproject.config.DynamicConfigEvent;
|
||||
import org.onosproject.config.DynamicConfigServiceAdapter;
|
||||
import org.onosproject.config.Filter;
|
||||
import org.onosproject.d.config.DeviceResourceIds;
|
||||
import org.onosproject.d.config.ResourceIds;
|
||||
import org.onosproject.d.config.sync.DeviceConfigSynchronizationProvider;
|
||||
import org.onosproject.d.config.sync.operation.SetRequest;
|
||||
import org.onosproject.d.config.sync.operation.SetRequest.Change;
|
||||
import org.onosproject.d.config.sync.operation.SetRequest.Change.Operation;
|
||||
import org.onosproject.d.config.sync.operation.SetResponse;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.net.config.NetworkConfigServiceAdapter;
|
||||
import org.onosproject.net.provider.ProviderId;
|
||||
import org.onosproject.yang.model.DataNode;
|
||||
import org.onosproject.yang.model.InnerNode;
|
||||
import org.onosproject.yang.model.LeafNode;
|
||||
import org.onosproject.yang.model.ResourceId;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
public class DynamicDeviceConfigSynchronizerTest {
|
||||
|
||||
static final String TEST_NS = "testNS";
|
||||
|
||||
static final ResourceId REL_INTERFACES = ResourceId.builder()
|
||||
.addBranchPointSchema("interfaces", TEST_NS)
|
||||
.build();
|
||||
|
||||
static final DeviceId DID = DeviceId.deviceId("test:device1");
|
||||
|
||||
DynamicDeviceConfigSynchronizer sut;
|
||||
|
||||
TestDynamicConfigService dyConService;
|
||||
|
||||
CountDownLatch providerCalled = new CountDownLatch(1);
|
||||
|
||||
/**
|
||||
* DynamicConfigService.readNode(ResourceId, Filter) stub.
|
||||
*/
|
||||
BiFunction<ResourceId, Filter, DataNode> onDcsRead;
|
||||
|
||||
BiFunction<DeviceId, SetRequest, CompletableFuture<SetResponse>> onSetConfiguration;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
||||
sut = new DynamicDeviceConfigSynchronizer();
|
||||
dyConService = new TestDynamicConfigService();
|
||||
sut.dynConfigService = dyConService;
|
||||
sut.netcfgService = new NetworkConfigServiceAdapter();
|
||||
|
||||
sut.activate();
|
||||
|
||||
sut.register(new MockDeviceConfigSynchronizerProvider());
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
sut.deactivate();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDispatchRequest() throws Exception {
|
||||
|
||||
ResourceId devicePath = DeviceResourceIds.toResourceId(DID);
|
||||
ResourceId cfgPath = REL_INTERFACES;
|
||||
ResourceId absPath = ResourceIds.concat(devicePath, cfgPath);
|
||||
ResourceId evtPath = ResourceIds.relativize(ROOT_ID, absPath);
|
||||
DynamicConfigEvent event = new DynamicConfigEvent(DynamicConfigEvent.Type.NODE_REPLACED, evtPath);
|
||||
|
||||
// assertions
|
||||
onDcsRead = (path, filter) -> {
|
||||
assertTrue(filter.isEmptyFilter());
|
||||
assertEquals("DCService get access by root relative RID", evtPath, path);
|
||||
return deviceConfigNode();
|
||||
};
|
||||
|
||||
onSetConfiguration = (deviceId, request) -> {
|
||||
assertEquals(DID, deviceId);
|
||||
assertEquals(1, request.changes().size());
|
||||
Change change = Iterables.get(request.changes(), 0);
|
||||
assertEquals("Provider get access by rel RID", REL_INTERFACES, change.path());
|
||||
assertEquals(Operation.REPLACE, change.op());
|
||||
assertEquals("interfaces", change.val().key().schemaId().name());
|
||||
// walk and test children if it adds value
|
||||
|
||||
providerCalled.countDown();
|
||||
return CompletableFuture.completedFuture(SetResponse.ok(request));
|
||||
};
|
||||
|
||||
// start test run
|
||||
|
||||
// imitate event from DCS
|
||||
dyConService.postEvent(event);
|
||||
|
||||
// assert that it reached the provider
|
||||
providerCalled.await(5, TimeUnit.HOURS);
|
||||
}
|
||||
|
||||
/**
|
||||
* DataNode for testing.
|
||||
*
|
||||
* <pre>
|
||||
* +-interfaces
|
||||
* |
|
||||
* +- interface{intf-name="en0"}
|
||||
* |
|
||||
* +- speed = "10G"
|
||||
* +- state = "up"
|
||||
*
|
||||
* </pre>
|
||||
* @return DataNode
|
||||
*/
|
||||
private DataNode deviceConfigNode() {
|
||||
InnerNode.Builder intfs = InnerNode.builder("interfaces", TEST_NS);
|
||||
intfs.type(DataNode.Type.SINGLE_INSTANCE_NODE);
|
||||
InnerNode.Builder intf = intfs.createChildBuilder("interface", TEST_NS);
|
||||
intf.type(DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE);
|
||||
intf.addKeyLeaf("name", TEST_NS, "Ethernet0/0");
|
||||
LeafNode.Builder speed = intf.createChildBuilder("mtu", TEST_NS, "1500");
|
||||
speed.type(DataNode.Type.SINGLE_INSTANCE_LEAF_VALUE_NODE);
|
||||
|
||||
intf.addNode(speed.build());
|
||||
intfs.addNode(intf.build());
|
||||
return intfs.build();
|
||||
}
|
||||
|
||||
private class TestDynamicConfigService extends DynamicConfigServiceAdapter {
|
||||
|
||||
public void postEvent(DynamicConfigEvent event) {
|
||||
listenerRegistry.process(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataNode readNode(ResourceId path, Filter filter) {
|
||||
return onDcsRead.apply(path, filter);
|
||||
}
|
||||
}
|
||||
|
||||
private class MockDeviceConfigSynchronizerProvider
|
||||
implements DeviceConfigSynchronizationProvider {
|
||||
|
||||
@Override
|
||||
public ProviderId id() {
|
||||
return new ProviderId(DID.uri().getScheme(), "test-provider");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<SetResponse> setConfiguration(DeviceId deviceId,
|
||||
SetRequest request) {
|
||||
return onSetConfiguration.apply(deviceId, request);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
BUNDLES = [
|
||||
"//apps/evpn-route-service/api:onos-apps-evpn-route-service-api",
|
||||
"//apps/evpn-route-service/app:onos-apps-evpn-route-service-app",
|
||||
]
|
||||
|
||||
onos_app(
|
||||
category = "Traffic Engineering",
|
||||
included_bundles = BUNDLES,
|
||||
title = "EVPN Routing",
|
||||
url = "http://onosproject.org",
|
||||
)
|
@ -1,3 +0,0 @@
|
||||
osgi_jar_with_tests(
|
||||
deps = CORE_DEPS,
|
||||
)
|
@ -1,138 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Represents a evpn instance.
|
||||
*/
|
||||
public final class EvpnInstance {
|
||||
|
||||
private final RouteDistinguisher rd;
|
||||
private final List<VpnRouteTarget> importRtList;
|
||||
private final List<VpnRouteTarget> exportRtList;
|
||||
private final EvpnInstanceName evpnName;
|
||||
|
||||
/**
|
||||
* Constructor to initialize the parameters.
|
||||
*
|
||||
* @param rd route distinguisher
|
||||
* @param importRtList import rotue targets
|
||||
* @param exportRtList export rotue targets
|
||||
* @param evpnName vpn instance name
|
||||
*/
|
||||
private EvpnInstance(RouteDistinguisher rd,
|
||||
List<VpnRouteTarget> importRtList,
|
||||
List<VpnRouteTarget> exportRtList,
|
||||
EvpnInstanceName evpnName) {
|
||||
checkNotNull(rd);
|
||||
//checkNotNull(rt);
|
||||
checkNotNull(evpnName);
|
||||
this.rd = rd;
|
||||
this.importRtList = importRtList;
|
||||
this.exportRtList = exportRtList;
|
||||
this.evpnName = evpnName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creats the instance of EvpnInstance.
|
||||
*
|
||||
* @param rd route distinguisher
|
||||
* @param importRtList import rotue targets
|
||||
* @param exportRtList export rotue targets
|
||||
* @param evpnName vpn instance name
|
||||
* @return EvpnInstance
|
||||
*/
|
||||
public static EvpnInstance evpnInstance(RouteDistinguisher rd,
|
||||
List<VpnRouteTarget> importRtList,
|
||||
List<VpnRouteTarget> exportRtList,
|
||||
EvpnInstanceName evpnName) {
|
||||
return new EvpnInstance(rd, importRtList, exportRtList, evpnName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter of RouteDistinguisher.
|
||||
*
|
||||
* @return RouteDistinguisher
|
||||
*/
|
||||
public RouteDistinguisher routeDistinguisher() {
|
||||
return rd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Route targets.
|
||||
*
|
||||
* @return RouteTarget List
|
||||
*/
|
||||
|
||||
public List<VpnRouteTarget> importRouteTarget() {
|
||||
return importRtList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Route targets.
|
||||
*
|
||||
* @return RouteTarget List
|
||||
*/
|
||||
public List<VpnRouteTarget> exportRouteTarget() {
|
||||
return exportRtList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter of vpn instance name.
|
||||
*
|
||||
* @return evpnName
|
||||
*/
|
||||
public EvpnInstanceName evpnName() {
|
||||
return evpnName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(rd, importRtList, exportRtList, evpnName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(other instanceof EvpnInstance)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EvpnInstance that = (EvpnInstance) other;
|
||||
|
||||
return Objects.equals(this.evpnName, that.evpnName)
|
||||
&& Objects.equals(this.rd, that.rd)
|
||||
&& Objects.equals(this.importRtList, that.importRtList)
|
||||
&& Objects.equals(this.exportRtList, that.exportRtList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this).add("evpnName", this.evpnName)
|
||||
.add("rd", this.rd).add("import rt", this.importRtList)
|
||||
.add("export rt", this.exportRtList).toString();
|
||||
}
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
|
||||
/**
|
||||
* Represents the EvpnInstanceName.
|
||||
*/
|
||||
public final class EvpnInstanceName {
|
||||
private final String evpnName;
|
||||
|
||||
/**
|
||||
* Constructor to initialize the parameters.
|
||||
*
|
||||
* @param evpnName EvpnInstanceName
|
||||
*/
|
||||
private EvpnInstanceName(String evpnName) {
|
||||
this.evpnName = evpnName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates instance of EvpnInstanceName.
|
||||
*
|
||||
* @param evpnName evpnName
|
||||
* @return evpnInstanceName
|
||||
*/
|
||||
public static EvpnInstanceName evpnName(String evpnName) {
|
||||
return new EvpnInstanceName(evpnName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get vpn instance name.
|
||||
*
|
||||
* @return evpnName
|
||||
*/
|
||||
public String getEvpnName() {
|
||||
return evpnName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(evpnName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (obj instanceof EvpnInstanceName) {
|
||||
EvpnInstanceName other = (EvpnInstanceName) obj;
|
||||
return Objects.equals(this.evpnName, other.evpnName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this).add("evpnName", evpnName).toString();
|
||||
}
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.onlab.packet.IpAddress;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
|
||||
/**
|
||||
* Represents a evpn instance nexthop.
|
||||
*/
|
||||
public final class EvpnInstanceNextHop {
|
||||
|
||||
private final IpAddress nextHop;
|
||||
private final Label label;
|
||||
|
||||
/**
|
||||
* Constructor to initialize the parameters.
|
||||
*
|
||||
* @param nextHop nexthop
|
||||
* @param label label
|
||||
*/
|
||||
private EvpnInstanceNextHop(IpAddress nextHop, Label label) {
|
||||
this.nextHop = nextHop;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
/**
|
||||
* creates instance of EvpnInstanceNextHop.
|
||||
*
|
||||
* @param nextHop nexthop
|
||||
* @param label label
|
||||
* @return evpnInstanceNexthop
|
||||
*/
|
||||
public static EvpnInstanceNextHop evpnNextHop(IpAddress nextHop,
|
||||
Label label) {
|
||||
return new EvpnInstanceNextHop(nextHop, label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next hop IP address.
|
||||
*
|
||||
* @return next hop
|
||||
*/
|
||||
public IpAddress nextHop() {
|
||||
return nextHop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the label.
|
||||
*
|
||||
* @return Label
|
||||
*/
|
||||
public Label label() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(nextHop, label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(other instanceof EvpnInstanceNextHop)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EvpnInstanceNextHop that = (EvpnInstanceNextHop) other;
|
||||
|
||||
return Objects.equals(this.nextHop(), that.nextHop())
|
||||
&& Objects.equals(this.label, that.label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this).add("nextHop", this.nextHop())
|
||||
.add("label", this.label).toString();
|
||||
}
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.onlab.packet.IpPrefix;
|
||||
import org.onlab.packet.MacAddress;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Represents a evpn instance prefix.
|
||||
*/
|
||||
public final class EvpnInstancePrefix {
|
||||
|
||||
private final MacAddress macAddress;
|
||||
private final IpPrefix ipPrefix;
|
||||
|
||||
/**
|
||||
* Constructor to initialize the parameters.
|
||||
*
|
||||
* @param macAddress Mac address
|
||||
* @param ipPrefix IP address
|
||||
*/
|
||||
private EvpnInstancePrefix(MacAddress macAddress,
|
||||
IpPrefix ipPrefix) {
|
||||
checkNotNull(macAddress);
|
||||
this.macAddress = macAddress;
|
||||
this.ipPrefix = ipPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the instance of EvpnInstancePrefix.
|
||||
*
|
||||
* @param macAddress Mac address
|
||||
* @param ipPrefix IP address
|
||||
* @return Evpn instance prefix
|
||||
*/
|
||||
public static EvpnInstancePrefix evpnPrefix(MacAddress macAddress,
|
||||
IpPrefix ipPrefix) {
|
||||
return new EvpnInstancePrefix(macAddress, ipPrefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the MAC of the route.
|
||||
*
|
||||
* @return MAC address
|
||||
*/
|
||||
public MacAddress macAddress() {
|
||||
return macAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the IP prefix of the route.
|
||||
*
|
||||
* @return IP prefix
|
||||
*/
|
||||
public IpPrefix ipPrefix() {
|
||||
return ipPrefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(macAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(other instanceof EvpnInstancePrefix)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EvpnInstancePrefix that = (EvpnInstancePrefix) other;
|
||||
|
||||
return Objects.equals(this.macAddress, that.macAddress)
|
||||
&& Objects.equals(this.ipPrefix, that.ipPrefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this).add("macAddress", this.macAddress)
|
||||
.add("ipAddress", this.ipPrefix).toString();
|
||||
}
|
||||
}
|
@ -1,219 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.onlab.packet.IpAddress;
|
||||
import org.onlab.packet.IpPrefix;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Represents a evpn instance route.
|
||||
*/
|
||||
public class EvpnInstanceRoute {
|
||||
|
||||
private final EvpnInstanceName evpnName;
|
||||
private final RouteDistinguisher rd;
|
||||
private List<VpnRouteTarget> importRtList;
|
||||
private List<VpnRouteTarget> exportRtList;
|
||||
private final EvpnInstancePrefix evpnInstancePrefix;
|
||||
private final EvpnInstanceNextHop evpnInstanceNextHop;
|
||||
private final IpPrefix prefix;
|
||||
private final IpAddress nextHop;
|
||||
private final Label label;
|
||||
|
||||
/**
|
||||
* Constructor to initialize the parameters.
|
||||
*
|
||||
* @param evpnName vpn instance name
|
||||
* @param rd route distinguisher
|
||||
* @param importRtList import route targets
|
||||
* @param exportRtList export route targets
|
||||
* @param evpnInstancePrefix evpn intance prefix
|
||||
* @param evpnInstanceNextHop evpn instance nexthop
|
||||
* @param prefix evpn prefix
|
||||
* @param nextHop evpn nexthop
|
||||
* @param label label
|
||||
*/
|
||||
public EvpnInstanceRoute(EvpnInstanceName evpnName,
|
||||
RouteDistinguisher rd,
|
||||
List<VpnRouteTarget> importRtList,
|
||||
List<VpnRouteTarget> exportRtList,
|
||||
EvpnInstancePrefix evpnInstancePrefix,
|
||||
EvpnInstanceNextHop evpnInstanceNextHop,
|
||||
IpPrefix prefix,
|
||||
IpAddress nextHop,
|
||||
Label label) {
|
||||
checkNotNull(evpnName);
|
||||
checkNotNull(prefix);
|
||||
//checkNotNull(nextHop); //can be NULL in MP un reach
|
||||
checkNotNull(rd);
|
||||
|
||||
this.evpnName = evpnName;
|
||||
this.rd = rd;
|
||||
this.importRtList = importRtList;
|
||||
this.exportRtList = exportRtList;
|
||||
this.prefix = prefix;
|
||||
this.nextHop = nextHop;
|
||||
this.evpnInstancePrefix = evpnInstancePrefix;
|
||||
this.evpnInstanceNextHop = evpnInstanceNextHop;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the evpnName.
|
||||
*
|
||||
* @return EvpnInstanceName
|
||||
*/
|
||||
public EvpnInstanceName evpnInstanceName() {
|
||||
return evpnName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the route distinguisher.
|
||||
*
|
||||
* @return RouteDistinguisher
|
||||
*/
|
||||
public RouteDistinguisher routeDistinguisher() {
|
||||
return rd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Route targets.
|
||||
*
|
||||
* @return RouteTarget List
|
||||
*/
|
||||
|
||||
public List<VpnRouteTarget> importRouteTarget() {
|
||||
return importRtList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Route targets.
|
||||
*
|
||||
* @return RouteTarget List
|
||||
*/
|
||||
public List<VpnRouteTarget> exportRouteTarget() {
|
||||
return exportRtList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set import list.
|
||||
*
|
||||
* @param importRtList import list
|
||||
*/
|
||||
public void setImportRtList(List<VpnRouteTarget> importRtList) {
|
||||
this.importRtList = importRtList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set export list.
|
||||
*
|
||||
* @param exportRtList export list
|
||||
*/
|
||||
public void setExportRtList(List<VpnRouteTarget> exportRtList) {
|
||||
this.exportRtList = exportRtList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns EvpnInstancePrefix of the evpn private route.
|
||||
*
|
||||
* @return EvpnInstancePrefix
|
||||
*/
|
||||
|
||||
public EvpnInstancePrefix getevpnInstancePrefix() {
|
||||
return evpnInstancePrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns EvpnInstanceNextHop of the evpn private route.
|
||||
*
|
||||
* @return EvpnInstancePrefix
|
||||
*/
|
||||
|
||||
public EvpnInstanceNextHop getEvpnInstanceNextHop() {
|
||||
return evpnInstanceNextHop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns prefix of the evpn private route.
|
||||
*
|
||||
* @return EvpnInstancePrefix
|
||||
*/
|
||||
public IpPrefix prefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the label.
|
||||
*
|
||||
* @return EvpnInstanceName
|
||||
*/
|
||||
public Label getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the label.
|
||||
*
|
||||
* @return EvpnInstanceName
|
||||
*/
|
||||
public IpAddress getNextHopl() {
|
||||
return nextHop;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(evpnName, prefix, nextHop,
|
||||
rd, importRtList, exportRtList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(other instanceof EvpnInstanceRoute)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EvpnInstanceRoute that = (EvpnInstanceRoute) other;
|
||||
|
||||
return Objects.equals(prefix, that.prefix)
|
||||
&& Objects.equals(nextHop, that.nextHop)
|
||||
&& Objects.equals(evpnName, that.evpnName)
|
||||
&& Objects.equals(rd, that.rd)
|
||||
&& Objects.equals(importRtList, that.importRtList)
|
||||
&& Objects.equals(exportRtList, that.exportRtList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this).add("prefix", prefix)
|
||||
.add("nextHop", nextHop)
|
||||
.add("rd", rd)
|
||||
.add("import rt", importRtList)
|
||||
.add("export rt", exportRtList)
|
||||
.add("evpnName", evpnName)
|
||||
.toString();
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import org.onosproject.event.AbstractEvent;
|
||||
|
||||
/**
|
||||
* Route event for signalling between the store and the manager.
|
||||
*/
|
||||
public class EvpnInternalRouteEvent extends
|
||||
AbstractEvent<EvpnInternalRouteEvent.Type, EvpnRouteSet> {
|
||||
|
||||
/**
|
||||
* Internal route event type.
|
||||
*/
|
||||
public enum Type {
|
||||
/**
|
||||
* Indicates a route was added to the store.
|
||||
*/
|
||||
ROUTE_ADDED,
|
||||
|
||||
/**
|
||||
* Indicates a route was removed from the store.
|
||||
*/
|
||||
ROUTE_REMOVED
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new internal route event.
|
||||
*
|
||||
* @param type route event type
|
||||
* @param subject route set
|
||||
*/
|
||||
public EvpnInternalRouteEvent(Type type, EvpnRouteSet subject) {
|
||||
super(type, subject);
|
||||
}
|
||||
|
||||
public EvpnInternalRouteEvent(Type type, EvpnRouteSet subject, long time) {
|
||||
super(type, subject, time);
|
||||
}
|
||||
}
|
@ -1,133 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.onlab.packet.IpAddress;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
|
||||
/**
|
||||
* Represents a evpn next hop.
|
||||
*/
|
||||
public final class EvpnNextHop {
|
||||
|
||||
private final IpAddress nextHop;
|
||||
private final List<VpnRouteTarget> importRtList;
|
||||
private final List<VpnRouteTarget> exportRtList;
|
||||
private final Label label;
|
||||
|
||||
/**
|
||||
* Constructor to initialize the parameters.
|
||||
*
|
||||
* @param nextHop evpn next hop
|
||||
* @param importRtList import route targets
|
||||
* @param importRtList export route targets
|
||||
* @param label label
|
||||
*/
|
||||
private EvpnNextHop(IpAddress nextHop, List<VpnRouteTarget> importRtList, List<VpnRouteTarget> exportRtList,
|
||||
Label label) {
|
||||
this.nextHop = nextHop;
|
||||
this.importRtList = importRtList;
|
||||
this.exportRtList = exportRtList;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the Evpn Next hop with given parameters.
|
||||
*
|
||||
* @param nextHop Next hop of the route
|
||||
* @param importRtList route target import list
|
||||
* @param exportRtList route target export list
|
||||
* @param label label of evpn route
|
||||
* @return EvpnNextHop
|
||||
*/
|
||||
public static EvpnNextHop evpnNextHop(IpAddress nextHop, List<VpnRouteTarget> importRtList,
|
||||
List<VpnRouteTarget> exportRtList,
|
||||
Label label) {
|
||||
return new EvpnNextHop(nextHop, importRtList, exportRtList, label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next hop IP address.
|
||||
*
|
||||
* @return next hop
|
||||
*/
|
||||
public IpAddress nextHop() {
|
||||
return nextHop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Route targets.
|
||||
*
|
||||
* @return RouteTarget List
|
||||
*/
|
||||
|
||||
public List<VpnRouteTarget> importRouteTarget() {
|
||||
return importRtList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Route targets.
|
||||
*
|
||||
* @return RouteTarget List
|
||||
*/
|
||||
public List<VpnRouteTarget> exportRouteTarget() {
|
||||
return exportRtList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the label of evpn route.
|
||||
*
|
||||
* @return Label
|
||||
*/
|
||||
public Label label() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(nextHop, importRtList, exportRtList, label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(other instanceof EvpnNextHop)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EvpnNextHop that = (EvpnNextHop) other;
|
||||
|
||||
return Objects.equals(this.nextHop(), that.nextHop())
|
||||
&& Objects.equals(this.importRtList, that.importRtList)
|
||||
&& Objects.equals(this.exportRtList, that.exportRtList)
|
||||
&& Objects.equals(this.label, that.label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this).add("nextHop", this.nextHop())
|
||||
.add("import rt list", this.importRtList).add("export rt list", this.exportRtList)
|
||||
.add("label", this.label).toString();
|
||||
}
|
||||
}
|
@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.onlab.packet.IpPrefix;
|
||||
import org.onlab.packet.MacAddress;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Represents a evpn prefix.
|
||||
*/
|
||||
public final class EvpnPrefix {
|
||||
|
||||
private final RouteDistinguisher rd;
|
||||
private final MacAddress macAddress;
|
||||
private final IpPrefix ipAddress;
|
||||
|
||||
/**
|
||||
* Constructor to initialize the parameters.
|
||||
*
|
||||
* @param rd route distinguisher
|
||||
* @param macAddress mac address
|
||||
* @param ipAddress IP address
|
||||
*/
|
||||
public EvpnPrefix(RouteDistinguisher rd, MacAddress macAddress,
|
||||
IpPrefix ipAddress) {
|
||||
checkNotNull(rd);
|
||||
checkNotNull(macAddress);
|
||||
checkNotNull(ipAddress);
|
||||
this.rd = rd;
|
||||
this.macAddress = macAddress;
|
||||
this.ipAddress = ipAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the evpn prefix by given parameters.
|
||||
*
|
||||
* @param rd route distinguisher
|
||||
* @param macAddress mac address
|
||||
* @param ipAddress ip address
|
||||
* @return EvpnPrefix
|
||||
*/
|
||||
public static EvpnPrefix evpnPrefix(RouteDistinguisher rd,
|
||||
MacAddress macAddress,
|
||||
IpPrefix ipAddress) {
|
||||
return new EvpnPrefix(rd, macAddress, ipAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the route distinguisher.
|
||||
*
|
||||
* @return RouteDistinguisher
|
||||
*/
|
||||
public RouteDistinguisher routeDistinguisher() {
|
||||
return rd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mac address.
|
||||
*
|
||||
* @return MacAddress
|
||||
*/
|
||||
public MacAddress macAddress() {
|
||||
return macAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the IP address.
|
||||
*
|
||||
* @return Ip4Address
|
||||
*/
|
||||
public IpPrefix ipAddress() {
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(rd, macAddress, ipAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(other instanceof EvpnPrefix)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EvpnPrefix that = (EvpnPrefix) other;
|
||||
|
||||
return Objects.equals(this.macAddress(), that.macAddress())
|
||||
&& Objects.equals(this.ipAddress, that.ipAddress)
|
||||
&& Objects.equals(this.rd, that.rd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this).add("macAddress", this.macAddress())
|
||||
.add("ipAddress", this.ipAddress()).add("rd", this.rd)
|
||||
.toString();
|
||||
}
|
||||
}
|
@ -1,281 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.onlab.packet.IpAddress;
|
||||
import org.onlab.packet.IpPrefix;
|
||||
import org.onlab.packet.MacAddress;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Represents a evpn route.
|
||||
*/
|
||||
public class EvpnRoute {
|
||||
|
||||
|
||||
/**
|
||||
* Source of the route.
|
||||
*/
|
||||
public enum Source {
|
||||
/**
|
||||
* Route came from app source.
|
||||
*/
|
||||
LOCAL,
|
||||
|
||||
/**
|
||||
* Route came from remote bgp peer source.
|
||||
*/
|
||||
REMOTE,
|
||||
}
|
||||
|
||||
private final Source source;
|
||||
private final MacAddress prefixMac;
|
||||
private final IpPrefix prefix;
|
||||
private final IpAddress nextHop;
|
||||
private final RouteDistinguisher rd;
|
||||
private List<VpnRouteTarget> importRtList;
|
||||
private List<VpnRouteTarget> exportRtList;
|
||||
private final Label label;
|
||||
|
||||
/**
|
||||
* Constructor to initialize the parameters.
|
||||
*
|
||||
* @param source route source
|
||||
* @param prefixMac mac address
|
||||
* @param prefix ip address
|
||||
* @param nextHop evpn nexthop
|
||||
* @param rd route distinguisher
|
||||
* @param importRtList import route targets
|
||||
* @param exportRtList export route targets
|
||||
* @param label evpn route label
|
||||
*/
|
||||
public EvpnRoute(Source source,
|
||||
MacAddress prefixMac,
|
||||
IpPrefix prefix,
|
||||
IpAddress nextHop,
|
||||
RouteDistinguisher rd,
|
||||
List<VpnRouteTarget> importRtList,
|
||||
List<VpnRouteTarget> exportRtList,
|
||||
Label label) {
|
||||
|
||||
checkNotNull(prefixMac);
|
||||
checkNotNull(prefix);
|
||||
//checkNotNull(nextHop);//next hop can be null in case of MP un reach.
|
||||
checkNotNull(rd);
|
||||
checkNotNull(label);
|
||||
this.source = checkNotNull(source);
|
||||
this.prefix = prefix;
|
||||
this.prefixMac = prefixMac;
|
||||
this.nextHop = nextHop;
|
||||
this.rd = rd;
|
||||
this.importRtList = importRtList;
|
||||
this.exportRtList = exportRtList;
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor to initialize the parameters.
|
||||
*
|
||||
* @param source route source
|
||||
* @param prefixMac mac address
|
||||
* @param prefix ip address
|
||||
* @param nextHop evpn nexthop
|
||||
* @param rdToString route distinguisher
|
||||
* @param importRtList import route targets
|
||||
* @param exportRtList export route targets
|
||||
* @param labelToInt evpn route label
|
||||
*/
|
||||
public EvpnRoute(Source source,
|
||||
MacAddress prefixMac,
|
||||
IpPrefix prefix,
|
||||
IpAddress nextHop,
|
||||
String rdToString,
|
||||
List<VpnRouteTarget> importRtList,
|
||||
List<VpnRouteTarget> exportRtList,
|
||||
int labelToInt) {
|
||||
checkNotNull(prefixMac);
|
||||
checkNotNull(prefix);
|
||||
//checkNotNull(nextHop); //next hop can be null in case of MP un reach.
|
||||
this.source = checkNotNull(source);
|
||||
this.prefix = prefix;
|
||||
this.prefixMac = prefixMac;
|
||||
this.nextHop = nextHop;
|
||||
this.rd = RouteDistinguisher.routeDistinguisher(rdToString);
|
||||
this.importRtList = importRtList;
|
||||
this.exportRtList = exportRtList;
|
||||
this.label = Label.label(labelToInt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the route source.
|
||||
*
|
||||
* @return route source
|
||||
*/
|
||||
public Source source() {
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the address.
|
||||
*
|
||||
* @return MacAddress
|
||||
*/
|
||||
public MacAddress prefixMac() {
|
||||
return prefixMac;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the IPv4 address.
|
||||
*
|
||||
* @return Ip4Address
|
||||
*/
|
||||
public IpPrefix prefixIp() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the IPv4 address.
|
||||
*
|
||||
* @return Ip4Address
|
||||
*/
|
||||
public EvpnPrefix evpnPrefix() {
|
||||
return new EvpnPrefix(rd, prefixMac,
|
||||
prefix);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the next hop IP address.
|
||||
*
|
||||
* @return Ip4Address
|
||||
*/
|
||||
public IpAddress ipNextHop() {
|
||||
return nextHop;
|
||||
}
|
||||
|
||||
public EvpnNextHop nextHop() {
|
||||
return EvpnNextHop.evpnNextHop(nextHop,
|
||||
importRtList,
|
||||
exportRtList,
|
||||
label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the routeDistinguisher.
|
||||
*
|
||||
* @return RouteDistinguisher
|
||||
*/
|
||||
public RouteDistinguisher routeDistinguisher() {
|
||||
return rd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Route targets.
|
||||
*
|
||||
* @return RouteTarget List
|
||||
*/
|
||||
|
||||
public List<VpnRouteTarget> importRouteTarget() {
|
||||
return importRtList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Route targets.
|
||||
*
|
||||
* @return RouteTarget List
|
||||
*/
|
||||
public List<VpnRouteTarget> exportRouteTarget() {
|
||||
return exportRtList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set import list.
|
||||
*
|
||||
* @param importRtList import list
|
||||
*/
|
||||
public void setImportRtList(List<VpnRouteTarget> importRtList) {
|
||||
this.importRtList = importRtList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set export list.
|
||||
*
|
||||
* @param exportRtList export list
|
||||
*/
|
||||
public void setExportRtList(List<VpnRouteTarget> exportRtList) {
|
||||
this.exportRtList = exportRtList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the label.
|
||||
*
|
||||
* @return Label
|
||||
*/
|
||||
public Label label() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(prefixMac,
|
||||
prefix,
|
||||
nextHop,
|
||||
rd,
|
||||
importRtList,
|
||||
exportRtList,
|
||||
label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(other instanceof EvpnRoute)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EvpnRoute that = (EvpnRoute) other;
|
||||
|
||||
return Objects.equals(prefixMac, that.prefixMac)
|
||||
&& Objects.equals(prefix, that.prefix)
|
||||
&& Objects.equals(nextHop, that.nextHop)
|
||||
&& Objects.equals(this.rd, that.rd)
|
||||
&& Objects.equals(this.importRtList, that.importRtList)
|
||||
&& Objects.equals(this.exportRtList, that.exportRtList)
|
||||
&& Objects.equals(this.label, that.label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this)
|
||||
.add("prefixMac", prefixMac)
|
||||
.add("prefix", prefix)
|
||||
.add("nextHop", nextHop)
|
||||
.add("rd", this.rd)
|
||||
.add("import rt", this.importRtList)
|
||||
.add("export rt", this.exportRtList)
|
||||
.add("label", this.label)
|
||||
.toString();
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Service allowing mutation of EVPN routing state.
|
||||
*/
|
||||
public interface EvpnRouteAdminService extends EvpnRouteService {
|
||||
|
||||
/**
|
||||
* Updates the given routes in the route service.
|
||||
*
|
||||
* @param routes collection of routes to update
|
||||
*/
|
||||
void update(Collection<EvpnRoute> routes);
|
||||
|
||||
/**
|
||||
* Withdraws the given routes from the route service.
|
||||
*
|
||||
* @param routes collection of routes to withdraw
|
||||
*/
|
||||
void withdraw(Collection<EvpnRoute> routes);
|
||||
}
|
@ -1,195 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.onlab.util.Tools;
|
||||
import org.onosproject.event.AbstractEvent;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
|
||||
/**
|
||||
* Describes an event about a route.
|
||||
*/
|
||||
public class EvpnRouteEvent extends AbstractEvent<EvpnRouteEvent.Type,
|
||||
EvpnRoute> {
|
||||
|
||||
private final EvpnRoute prevSubject;
|
||||
private final Collection<EvpnRoute> alternativeRoutes;
|
||||
|
||||
/**
|
||||
* Route event type.
|
||||
*/
|
||||
public enum Type {
|
||||
|
||||
/**
|
||||
* Route is new and the next hop is resolved.
|
||||
* <p>
|
||||
* The subject of this event should be the route being added.
|
||||
* The prevSubject of this event should be null.
|
||||
* </p>
|
||||
*/
|
||||
ROUTE_ADDED,
|
||||
|
||||
/**
|
||||
* Route has updated information.
|
||||
* <p>
|
||||
* The subject of this event should be the new route.
|
||||
* The prevSubject of this event should be the old route.
|
||||
* </p>
|
||||
*/
|
||||
ROUTE_UPDATED,
|
||||
|
||||
/**
|
||||
* Route was removed or the next hop becomes unresolved.
|
||||
* <p>
|
||||
* The subject of this event should be the route being removed.
|
||||
* The prevSubject of this event should be null.
|
||||
* </p>
|
||||
*/
|
||||
ROUTE_REMOVED,
|
||||
|
||||
/**
|
||||
* The set of alternative routes for the subject's prefix has changed,
|
||||
* but the best route is still the same.
|
||||
* <p>
|
||||
* The subject is the best route for the prefix (which has already been
|
||||
* notified in a previous event).
|
||||
* The prevSubject of this event is null.
|
||||
* The alternatives contains the new set of alternative routes.
|
||||
* </p>
|
||||
*/
|
||||
ALTERNATIVE_ROUTES_CHANGED
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new route event without specifying previous subject.
|
||||
*
|
||||
* @param type event type
|
||||
* @param subject event subject
|
||||
*/
|
||||
public EvpnRouteEvent(Type type, EvpnRoute subject) {
|
||||
this(type, subject, null, Collections.emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new route event without specifying previous subject.
|
||||
*
|
||||
* @param type event type
|
||||
* @param subject event subject
|
||||
* @param alternatives alternative routes for subject's prefix
|
||||
*/
|
||||
public EvpnRouteEvent(Type type, EvpnRoute subject,
|
||||
Collection<EvpnRoute> alternatives) {
|
||||
this(type, subject, null, alternatives);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new route event.
|
||||
*
|
||||
* @param type event type
|
||||
* @param subject event subject
|
||||
* @param time event time
|
||||
*/
|
||||
protected EvpnRouteEvent(Type type, EvpnRoute subject, long time) {
|
||||
super(type, subject, time);
|
||||
this.prevSubject = null;
|
||||
|
||||
this.alternativeRoutes = Collections.emptySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new route event with previous subject.
|
||||
*
|
||||
* @param type event type
|
||||
* @param subject event subject
|
||||
* @param prevSubject previous subject
|
||||
*/
|
||||
public EvpnRouteEvent(Type type, EvpnRoute subject, EvpnRoute prevSubject) {
|
||||
this(type, subject, prevSubject, Collections.emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new route event with a previous subject and alternative routes.
|
||||
*
|
||||
* @param type event type
|
||||
* @param subject event subject
|
||||
* @param prevSubject previous subject
|
||||
* @param alternatives alternative routes for subject's prefix
|
||||
*/
|
||||
public EvpnRouteEvent(Type type, EvpnRoute subject, EvpnRoute prevSubject,
|
||||
Collection<EvpnRoute> alternatives) {
|
||||
super(type, subject);
|
||||
this.prevSubject = prevSubject;
|
||||
this.alternativeRoutes = alternatives;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the previous subject of the event.
|
||||
*
|
||||
* @return previous subject to which this event pertains
|
||||
*/
|
||||
public EvpnRoute prevSubject() {
|
||||
return prevSubject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of alternative routes for the subject's prefix.
|
||||
*
|
||||
* @return alternative routes
|
||||
*/
|
||||
public Collection<EvpnRoute> alternatives() {
|
||||
return alternativeRoutes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(subject(), type(), prevSubject(), alternativeRoutes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(other instanceof EvpnRouteEvent)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EvpnRouteEvent that = (EvpnRouteEvent) other;
|
||||
|
||||
return Objects.equals(this.subject(), that.subject()) &&
|
||||
Objects.equals(this.type(), that.type()) &&
|
||||
Objects.equals(this.prevSubject, that.prevSubject) &&
|
||||
Objects.equals(this.alternativeRoutes, that.alternativeRoutes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this)
|
||||
.add("time", Tools.defaultOffsetDataTime(time()))
|
||||
.add("type", type())
|
||||
.add("subject", subject())
|
||||
.add("prevSubject", prevSubject)
|
||||
.add("alternatives", alternativeRoutes)
|
||||
.toString();
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import org.onosproject.event.EventListener;
|
||||
|
||||
/**
|
||||
* Listener for route events.
|
||||
*/
|
||||
public interface EvpnRouteListener extends EventListener<EvpnRouteEvent> {
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.onosproject.event.ListenerService;
|
||||
|
||||
/**
|
||||
* EVPN route service.
|
||||
*/
|
||||
public interface EvpnRouteService extends ListenerService<EvpnRouteEvent,
|
||||
EvpnRouteListener> {
|
||||
|
||||
|
||||
/**
|
||||
* Returns the set of route tables in the system.
|
||||
*
|
||||
* @return collection of route table IDs.
|
||||
*/
|
||||
Collection<EvpnRouteTableId> getRouteTables();
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* A set of routes for a particular prefix in a route table.
|
||||
*/
|
||||
public class EvpnRouteSet {
|
||||
private final EvpnRouteTableId tableId;
|
||||
|
||||
private final EvpnPrefix prefix;
|
||||
private final Set<EvpnRoute> routes;
|
||||
|
||||
/**
|
||||
* Creates a new route set.
|
||||
*
|
||||
* @param tableId route table ID
|
||||
* @param prefix IP prefix
|
||||
* @param routes routes for the given prefix
|
||||
*/
|
||||
public EvpnRouteSet(EvpnRouteTableId tableId, EvpnPrefix prefix, Set<EvpnRoute>
|
||||
routes) {
|
||||
this.tableId = checkNotNull(tableId);
|
||||
this.prefix = checkNotNull(prefix);
|
||||
this.routes = ImmutableSet.copyOf(checkNotNull(routes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the route table ID.
|
||||
*
|
||||
* @return route table ID
|
||||
*/
|
||||
public EvpnRouteTableId tableId() {
|
||||
return tableId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the IP prefix.
|
||||
*
|
||||
* @return IP prefix
|
||||
*/
|
||||
public EvpnPrefix prefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of routes.
|
||||
*
|
||||
* @return routes
|
||||
*/
|
||||
public Set<EvpnRoute> routes() {
|
||||
return routes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(tableId, prefix, routes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(other instanceof EvpnRouteSet)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EvpnRouteSet that = (EvpnRouteSet) other;
|
||||
|
||||
return Objects.equals(this.tableId, that.tableId) &&
|
||||
Objects.equals(this.prefix, that.prefix) &&
|
||||
Objects.equals(this.routes, that.routes);
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import org.onlab.packet.IpAddress;
|
||||
import org.onosproject.store.Store;
|
||||
|
||||
/**
|
||||
* EVPN route store.
|
||||
*/
|
||||
public interface EvpnRouteStore extends Store<EvpnInternalRouteEvent,
|
||||
EvpnRouteStoreDelegate> {
|
||||
|
||||
/**
|
||||
* Adds or updates the given route in the store.
|
||||
*
|
||||
* @param route route to add or update
|
||||
*/
|
||||
void updateRoute(EvpnRoute route);
|
||||
|
||||
/**
|
||||
* Removes the given route from the store.
|
||||
*
|
||||
* @param route route to remove
|
||||
*/
|
||||
void removeRoute(EvpnRoute route);
|
||||
|
||||
/**
|
||||
* Returns the IDs for all route tables in the store.
|
||||
*
|
||||
* @return route table IDs
|
||||
*/
|
||||
Set<EvpnRouteTableId> getRouteTables();
|
||||
|
||||
/**
|
||||
* Returns the routes in the given route table, grouped by prefix.
|
||||
*
|
||||
* @param table route table ID
|
||||
* @return routes
|
||||
*/
|
||||
Collection<EvpnRouteSet> getRoutes(EvpnRouteTableId table);
|
||||
|
||||
/**
|
||||
* Returns the routes that point to the given next hop IP address.
|
||||
*
|
||||
* @param ip IP address of the next hop
|
||||
* @return routes for the given next hop
|
||||
*/
|
||||
// TODO think about including route table info
|
||||
Collection<EvpnRoute> getRoutesForNextHop(IpAddress ip);
|
||||
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import org.onosproject.store.StoreDelegate;
|
||||
|
||||
/**
|
||||
* Route store delegate abstraction.
|
||||
*/
|
||||
public interface EvpnRouteStoreDelegate extends
|
||||
StoreDelegate<EvpnInternalRouteEvent> {
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Identifier for an EVPN routing table.
|
||||
*/
|
||||
public class EvpnRouteTableId {
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Creates a new route table ID.
|
||||
*
|
||||
* @param name unique name for the route table
|
||||
*/
|
||||
public EvpnRouteTableId(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the route table.
|
||||
*
|
||||
* @return table name
|
||||
*/
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (obj instanceof EvpnRouteTableId) {
|
||||
EvpnRouteTableId that = (EvpnRouteTableId) obj;
|
||||
|
||||
return Objects.equals(this.name, that.name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.onlab.packet.IpAddress;
|
||||
|
||||
/**
|
||||
* Represents a route table that stores routes.
|
||||
*/
|
||||
public interface EvpnTable {
|
||||
|
||||
/**
|
||||
* Adds a route to the route table.
|
||||
*
|
||||
* @param route route
|
||||
*/
|
||||
void update(EvpnRoute route);
|
||||
|
||||
/**
|
||||
* Removes a route from the route table.
|
||||
*
|
||||
* @param route route
|
||||
*/
|
||||
void remove(EvpnRoute route);
|
||||
|
||||
/**
|
||||
* Returns the route table ID.
|
||||
*
|
||||
* @return route table ID
|
||||
*/
|
||||
EvpnRouteTableId id();
|
||||
|
||||
/**
|
||||
* Returns all routes in the route table.
|
||||
*
|
||||
* @return collection of routes, grouped by prefix
|
||||
*/
|
||||
Collection<EvpnRouteSet> getRoutes();
|
||||
|
||||
/**
|
||||
* Returns the routes in this table pertaining to a given prefix.
|
||||
*
|
||||
* @param prefix IP prefix
|
||||
* @return routes for the prefix
|
||||
*/
|
||||
EvpnRouteSet getRoutes(EvpnPrefix prefix);
|
||||
|
||||
/**
|
||||
* Returns all routes that have the given next hop.
|
||||
*
|
||||
* @param nextHop next hop IP address
|
||||
* @return collection of routes
|
||||
*/
|
||||
Collection<EvpnRoute> getRoutesForNextHop(IpAddress nextHop);
|
||||
|
||||
/**
|
||||
* Releases route table resources held locally.
|
||||
*/
|
||||
void shutdown();
|
||||
|
||||
/**
|
||||
* Releases route table resources across the entire cluster.
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
|
||||
/**
|
||||
* Represents label of the route.
|
||||
*/
|
||||
public final class Label {
|
||||
private final int label;
|
||||
|
||||
/**
|
||||
* Constructor to initialize parameters.
|
||||
*
|
||||
* @param label route label
|
||||
*/
|
||||
private Label(int label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the label for evpn route.
|
||||
*
|
||||
* @param label label of evpn route
|
||||
* @return Label
|
||||
*/
|
||||
public static Label label(int label) {
|
||||
return new Label(label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the label.
|
||||
*
|
||||
* @return label
|
||||
*/
|
||||
public int getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (obj instanceof Label) {
|
||||
Label other = (Label) obj;
|
||||
return Objects.equals(label, other.label);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this).add("label", label).toString();
|
||||
}
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Represents Route Distinguisher of device in the network.
|
||||
*/
|
||||
public final class RouteDistinguisher {
|
||||
private final String routeDistinguisher;
|
||||
|
||||
/**
|
||||
* Constructor to initialize parameters.
|
||||
*
|
||||
* @param routeDistinguisher route distinguisher
|
||||
*/
|
||||
private RouteDistinguisher(String routeDistinguisher) {
|
||||
this.routeDistinguisher = routeDistinguisher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the route distinguisher.
|
||||
*
|
||||
* @param routeDistinguisher route distinguisher
|
||||
* @return RouteDistinguisher
|
||||
*/
|
||||
public static RouteDistinguisher routeDistinguisher(String routeDistinguisher) {
|
||||
checkNotNull(routeDistinguisher);
|
||||
return new RouteDistinguisher(routeDistinguisher);
|
||||
}
|
||||
|
||||
/**
|
||||
* get route distinguisher.
|
||||
*
|
||||
* @return distinguisher
|
||||
*/
|
||||
public String getRouteDistinguisher() {
|
||||
return routeDistinguisher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(routeDistinguisher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (obj instanceof RouteDistinguisher) {
|
||||
RouteDistinguisher other = (RouteDistinguisher) obj;
|
||||
return Objects.equals(this.routeDistinguisher, other.routeDistinguisher);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this)
|
||||
.add("routeDistinguisher", this.routeDistinguisher).toString();
|
||||
}
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
|
||||
/**
|
||||
* Represents Route target of vpn instance.
|
||||
*/
|
||||
public final class VpnRouteTarget {
|
||||
private final String routeTarget;
|
||||
|
||||
/**
|
||||
* Constructor to initialize parameters.
|
||||
*
|
||||
* @param routeTarget route target
|
||||
*/
|
||||
private VpnRouteTarget(String routeTarget) {
|
||||
this.routeTarget = routeTarget;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the vpn route target.
|
||||
*
|
||||
* @param routeTarget route target
|
||||
* @return route target
|
||||
*/
|
||||
public static VpnRouteTarget routeTarget(String routeTarget) {
|
||||
return new VpnRouteTarget(routeTarget);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the route target.
|
||||
*
|
||||
* @return route target
|
||||
*/
|
||||
public String getRouteTarget() {
|
||||
return routeTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(routeTarget);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (obj instanceof VpnRouteTarget) {
|
||||
VpnRouteTarget other = (VpnRouteTarget) obj;
|
||||
return Objects.equals(routeTarget, other.routeTarget);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this).add("routeTarget", routeTarget).toString();
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-present Open Networking Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Unicast routing service.
|
||||
*/
|
||||
package org.onosproject.evpnrouteservice;
|
@ -1,8 +0,0 @@
|
||||
COMPILE_DEPS = CORE_DEPS + KRYO + [
|
||||
"//core/store/serializers:onos-core-serializers",
|
||||
"//apps/evpn-route-service/api:onos-apps-evpn-route-service-api",
|
||||
]
|
||||
|
||||
osgi_jar_with_tests(
|
||||
deps = COMPILE_DEPS,
|
||||
)
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice.impl;
|
||||
|
||||
import org.onosproject.evpnrouteservice.EvpnRouteEvent;
|
||||
|
||||
/**
|
||||
* Queues updates for a route listener to ensure they are received in the
|
||||
* correct order.
|
||||
*/
|
||||
interface EvpnListenerQueue {
|
||||
|
||||
/**
|
||||
* Posts an event to the listener.
|
||||
*
|
||||
* @param event event
|
||||
*/
|
||||
void post(EvpnRouteEvent event);
|
||||
|
||||
/**
|
||||
* Initiates event delivery to the listener.
|
||||
*/
|
||||
void start();
|
||||
|
||||
/**
|
||||
* Halts event delivery to the listener.
|
||||
*/
|
||||
void stop();
|
||||
}
|
@ -1,274 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice.impl;
|
||||
|
||||
import org.onosproject.evpnrouteservice.EvpnInternalRouteEvent;
|
||||
import org.onosproject.evpnrouteservice.EvpnRoute;
|
||||
import org.onosproject.evpnrouteservice.EvpnRouteAdminService;
|
||||
import org.onosproject.evpnrouteservice.EvpnRouteEvent;
|
||||
import org.onosproject.evpnrouteservice.EvpnRouteListener;
|
||||
import org.onosproject.evpnrouteservice.EvpnRouteService;
|
||||
import org.onosproject.evpnrouteservice.EvpnRouteSet;
|
||||
import org.onosproject.evpnrouteservice.EvpnRouteStore;
|
||||
import org.onosproject.evpnrouteservice.EvpnRouteStoreDelegate;
|
||||
import org.onosproject.evpnrouteservice.EvpnRouteTableId;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Deactivate;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.concurrent.GuardedBy;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import static java.util.concurrent.Executors.newSingleThreadExecutor;
|
||||
import static org.onlab.util.Tools.groupedThreads;
|
||||
|
||||
/**
|
||||
* Implementation of the EVPN route service.
|
||||
*/
|
||||
@Component(service = { EvpnRouteService.class, EvpnRouteAdminService.class })
|
||||
public class EvpnRouteManager implements EvpnRouteService,
|
||||
EvpnRouteAdminService {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected EvpnRouteStore evpnRouteStore;
|
||||
|
||||
@GuardedBy(value = "this")
|
||||
private Map<EvpnRouteListener, EvpnListenerQueue> listeners = new
|
||||
HashMap<>();
|
||||
|
||||
private ThreadFactory threadFactory;
|
||||
|
||||
private EvpnRouteStoreDelegate evpnRouteStoreDelegate = new
|
||||
InternalEvpnRouteStoreDelegate();
|
||||
|
||||
@Activate
|
||||
protected void activate() {
|
||||
threadFactory = groupedThreads("onos/route", "listener-%d", log);
|
||||
evpnRouteStore.setDelegate(evpnRouteStoreDelegate);
|
||||
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
protected void deactivate() {
|
||||
evpnRouteStore.unsetDelegate(evpnRouteStoreDelegate);
|
||||
synchronized (this) {
|
||||
listeners.values().forEach(EvpnListenerQueue::stop);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
* In a departure from other services in ONOS, calling addListener will
|
||||
* cause all current routes to be pushed to the listener before any new
|
||||
* events are sent. This allows a listener to easily get the exact set of
|
||||
* routes without worrying about missing any.
|
||||
*
|
||||
* @param listener listener to be added
|
||||
*/
|
||||
@Override
|
||||
public void addListener(EvpnRouteListener listener) {
|
||||
synchronized (this) {
|
||||
EvpnListenerQueue l = createListenerQueue(listener);
|
||||
|
||||
evpnRouteStore.getRouteTables().forEach(routeTableId
|
||||
-> {
|
||||
Collection<EvpnRouteSet> routes
|
||||
= evpnRouteStore.getRoutes(routeTableId);
|
||||
if (routes != null) {
|
||||
routes.forEach(route -> {
|
||||
Collection<EvpnRoute> evpnRoutes = route.routes();
|
||||
for (EvpnRoute evpnRoute : evpnRoutes) {
|
||||
l.post(new EvpnRouteEvent(
|
||||
EvpnRouteEvent.Type.ROUTE_ADDED,
|
||||
evpnRoute,
|
||||
route.routes()));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
listeners.put(listener, l);
|
||||
|
||||
l.start();
|
||||
log.debug("Route synchronization complete");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener(EvpnRouteListener listener) {
|
||||
synchronized (this) {
|
||||
EvpnListenerQueue l = listeners.remove(listener);
|
||||
if (l != null) {
|
||||
l.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Posts an event to all listeners.
|
||||
*
|
||||
* @param event event
|
||||
*/
|
||||
|
||||
private void post(EvpnRouteEvent event) {
|
||||
if (event != null) {
|
||||
log.debug("Sending event {}", event);
|
||||
synchronized (this) {
|
||||
listeners.values().forEach(l -> l.post(event));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Collection<EvpnRouteTableId> getRouteTables() {
|
||||
return evpnRouteStore.getRouteTables();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Collection<EvpnRoute> routes) {
|
||||
synchronized (this) {
|
||||
routes.forEach(route -> {
|
||||
log.debug("Received update {}", route);
|
||||
evpnRouteStore.updateRoute(route);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void withdraw(Collection<EvpnRoute> routes) {
|
||||
synchronized (this) {
|
||||
routes.forEach(route -> {
|
||||
log.debug("Received withdraw {}", route);
|
||||
evpnRouteStore.removeRoute(route);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new listener queue.
|
||||
*
|
||||
* @param listener route listener
|
||||
* @return listener queue
|
||||
*/
|
||||
DefaultListenerQueue createListenerQueue(EvpnRouteListener listener) {
|
||||
return new DefaultListenerQueue(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default route listener queue.
|
||||
*/
|
||||
private class DefaultListenerQueue implements EvpnListenerQueue {
|
||||
|
||||
private final ExecutorService executorService;
|
||||
private final BlockingQueue<EvpnRouteEvent> queue;
|
||||
private final EvpnRouteListener listener;
|
||||
|
||||
/**
|
||||
* Creates a new listener queue.
|
||||
*
|
||||
* @param listener route listener to queue updates for
|
||||
*/
|
||||
public DefaultListenerQueue(EvpnRouteListener listener) {
|
||||
this.listener = listener;
|
||||
queue = new LinkedBlockingQueue<>();
|
||||
executorService = newSingleThreadExecutor(threadFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void post(EvpnRouteEvent event) {
|
||||
queue.add(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
executorService.execute(this::poll);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
executorService.shutdown();
|
||||
}
|
||||
|
||||
private void poll() {
|
||||
while (true) {
|
||||
try {
|
||||
listener.event(queue.take());
|
||||
} catch (InterruptedException e) {
|
||||
log.info("Route listener event thread shutting down: {}", e.getMessage());
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
log.warn("Exception during route event handler", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate to receive events from the route store.
|
||||
*/
|
||||
private class InternalEvpnRouteStoreDelegate implements
|
||||
EvpnRouteStoreDelegate {
|
||||
EvpnRouteSet routes;
|
||||
|
||||
@Override
|
||||
public void notify(EvpnInternalRouteEvent event) {
|
||||
switch (event.type()) {
|
||||
case ROUTE_ADDED:
|
||||
routes = event.subject();
|
||||
if (routes != null) {
|
||||
Collection<EvpnRoute> evpnRoutes = routes.routes();
|
||||
for (EvpnRoute evpnRoute : evpnRoutes) {
|
||||
post(new EvpnRouteEvent(
|
||||
EvpnRouteEvent.Type.ROUTE_ADDED,
|
||||
evpnRoute,
|
||||
routes.routes()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ROUTE_REMOVED:
|
||||
routes = event.subject();
|
||||
if (routes != null) {
|
||||
Collection<EvpnRoute> evpnRoutes = routes.routes();
|
||||
for (EvpnRoute evpnRoute : evpnRoutes) {
|
||||
post(new EvpnRouteEvent(
|
||||
EvpnRouteEvent.Type.ROUTE_REMOVED,
|
||||
evpnRoute,
|
||||
routes.routes()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-present Open Networking Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implementation of route service.
|
||||
*/
|
||||
package org.onosproject.evpnrouteservice.impl;
|
@ -1,201 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice.store;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.onlab.packet.IpAddress;
|
||||
import org.onlab.util.KryoNamespace;
|
||||
import org.onosproject.evpnrouteservice.EvpnInternalRouteEvent;
|
||||
import org.onosproject.evpnrouteservice.EvpnRoute;
|
||||
import org.onosproject.evpnrouteservice.EvpnRouteSet;
|
||||
import org.onosproject.evpnrouteservice.EvpnRouteStore;
|
||||
import org.onosproject.evpnrouteservice.EvpnRouteStoreDelegate;
|
||||
import org.onosproject.evpnrouteservice.EvpnRouteTableId;
|
||||
import org.onosproject.evpnrouteservice.EvpnTable;
|
||||
import org.onosproject.store.AbstractStore;
|
||||
import org.onosproject.store.service.DistributedSet;
|
||||
import org.onosproject.store.service.Serializer;
|
||||
import org.onosproject.store.service.SetEvent;
|
||||
import org.onosproject.store.service.SetEventListener;
|
||||
import org.onosproject.store.service.StorageService;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Deactivate;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import static org.onlab.util.Tools.groupedThreads;
|
||||
|
||||
/**
|
||||
* Route store based on distributed storage.
|
||||
*/
|
||||
@Component(service = EvpnRouteStore.class)
|
||||
public class DistributedEvpnRouteStore extends
|
||||
AbstractStore<EvpnInternalRouteEvent,
|
||||
EvpnRouteStoreDelegate>
|
||||
implements EvpnRouteStore {
|
||||
|
||||
private static final Logger log = LoggerFactory
|
||||
.getLogger(DistributedEvpnRouteStore.class);
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
public StorageService storageService;
|
||||
|
||||
private static final EvpnRouteTableId EVPN_IPV4 = new EvpnRouteTableId("evpn_ipv4");
|
||||
private static final EvpnRouteTableId EVPN_IPV6 = new EvpnRouteTableId("evpn_ipv6");
|
||||
|
||||
private final SetEventListener<EvpnRouteTableId> masterRouteTableListener =
|
||||
new MasterRouteTableListener();
|
||||
private final EvpnRouteStoreDelegate ourDelegate = new
|
||||
InternalEvpnRouteStoreDelegate();
|
||||
|
||||
// Stores the route tables that have been created
|
||||
public DistributedSet<EvpnRouteTableId> masterRouteTable;
|
||||
// Local memory map to store route table object
|
||||
public Map<EvpnRouteTableId, EvpnTable> routeTables;
|
||||
|
||||
private ExecutorService executor;
|
||||
|
||||
|
||||
/**
|
||||
* Sets up distributed route store.
|
||||
*/
|
||||
@Activate
|
||||
public void activate() {
|
||||
routeTables = new ConcurrentHashMap<>();
|
||||
executor = Executors.newSingleThreadExecutor(groupedThreads("onos/route", "store", log));
|
||||
|
||||
KryoNamespace masterRouteTableSerializer = KryoNamespace.newBuilder()
|
||||
.register(EvpnRouteTableId.class)
|
||||
.build();
|
||||
|
||||
masterRouteTable = storageService.<EvpnRouteTableId>setBuilder()
|
||||
.withName("onos-master-route-table")
|
||||
.withSerializer(Serializer.using(masterRouteTableSerializer))
|
||||
.build()
|
||||
.asDistributedSet();
|
||||
|
||||
masterRouteTable.forEach(this::createRouteTable);
|
||||
|
||||
masterRouteTable.addListener(masterRouteTableListener);
|
||||
|
||||
// Add default tables (add is idempotent)
|
||||
masterRouteTable.add(EVPN_IPV4);
|
||||
masterRouteTable.add(EVPN_IPV6);
|
||||
|
||||
log.info("Started");
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up distributed route store.
|
||||
*/
|
||||
@Deactivate
|
||||
public void deactivate() {
|
||||
masterRouteTable.removeListener(masterRouteTableListener);
|
||||
|
||||
routeTables.values().forEach(EvpnTable::shutdown);
|
||||
|
||||
log.info("Stopped");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateRoute(EvpnRoute route) {
|
||||
getDefaultRouteTable(route).update(route);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeRoute(EvpnRoute route) {
|
||||
getDefaultRouteTable(route).remove(route);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<EvpnRouteTableId> getRouteTables() {
|
||||
return ImmutableSet.copyOf(masterRouteTable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<EvpnRouteSet> getRoutes(EvpnRouteTableId table) {
|
||||
EvpnTable routeTable = routeTables.get(table);
|
||||
if (routeTable == null) {
|
||||
return Collections.emptySet();
|
||||
} else {
|
||||
return ImmutableSet.copyOf(routeTable.getRoutes());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<EvpnRoute> getRoutesForNextHop(IpAddress ip) {
|
||||
return getDefaultRouteTable(ip).getRoutesForNextHop(ip);
|
||||
}
|
||||
|
||||
private void createRouteTable(EvpnRouteTableId tableId) {
|
||||
routeTables.computeIfAbsent(tableId, id -> new EvpnRouteTable(id,
|
||||
ourDelegate, storageService, executor));
|
||||
}
|
||||
|
||||
private void destroyRouteTable(EvpnRouteTableId tableId) {
|
||||
EvpnTable table = routeTables.remove(tableId);
|
||||
if (table != null) {
|
||||
table.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
private EvpnTable getDefaultRouteTable(EvpnRoute route) {
|
||||
return getDefaultRouteTable(route.prefixIp().address());
|
||||
}
|
||||
|
||||
private EvpnTable getDefaultRouteTable(IpAddress ip) {
|
||||
EvpnRouteTableId routeTableId = (ip.isIp4()) ? EVPN_IPV4 : EVPN_IPV6;
|
||||
return routeTables.getOrDefault(routeTableId, EmptyEvpnRouteTable
|
||||
.instance());
|
||||
}
|
||||
|
||||
private class InternalEvpnRouteStoreDelegate implements
|
||||
EvpnRouteStoreDelegate {
|
||||
@Override
|
||||
public void notify(EvpnInternalRouteEvent event) {
|
||||
executor.execute(() -> DistributedEvpnRouteStore
|
||||
.this.notifyDelegate(event));
|
||||
}
|
||||
}
|
||||
|
||||
private class MasterRouteTableListener implements SetEventListener<EvpnRouteTableId> {
|
||||
@Override
|
||||
public void event(SetEvent<EvpnRouteTableId> event) {
|
||||
switch (event.type()) {
|
||||
case ADD:
|
||||
executor.execute(() -> createRouteTable(event.entry()));
|
||||
break;
|
||||
case REMOVE:
|
||||
executor.execute(() -> destroyRouteTable(event.entry()));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice.store;
|
||||
|
||||
import org.onlab.packet.IpAddress;
|
||||
import org.onosproject.evpnrouteservice.EvpnPrefix;
|
||||
import org.onosproject.evpnrouteservice.EvpnRoute;
|
||||
import org.onosproject.evpnrouteservice.EvpnRouteSet;
|
||||
import org.onosproject.evpnrouteservice.EvpnRouteTableId;
|
||||
import org.onosproject.evpnrouteservice.EvpnTable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Route table that contains no routes.
|
||||
*/
|
||||
public final class EmptyEvpnRouteTable implements EvpnTable {
|
||||
|
||||
private final EvpnRouteTableId id = new EvpnRouteTableId("empty");
|
||||
|
||||
private static final EmptyEvpnRouteTable INSTANCE = new EmptyEvpnRouteTable();
|
||||
|
||||
/**
|
||||
* Returns the instance of the empty route table.
|
||||
*
|
||||
* @return empty route table
|
||||
*/
|
||||
public static EmptyEvpnRouteTable instance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
private EmptyEvpnRouteTable() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(EvpnRoute route) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(EvpnRoute route) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public EvpnRouteTableId id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<EvpnRouteSet> getRoutes() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EvpnRouteSet getRoutes(EvpnPrefix prefix) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<EvpnRoute> getRoutesForNextHop(IpAddress nextHop) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
|
||||
}
|
||||
}
|
@ -1,230 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnrouteservice.store;
|
||||
|
||||
import org.onlab.packet.IpAddress;
|
||||
import org.onlab.packet.IpPrefix;
|
||||
import org.onlab.packet.MacAddress;
|
||||
import org.onlab.util.KryoNamespace;
|
||||
import org.onosproject.evpnrouteservice.EvpnInternalRouteEvent;
|
||||
import org.onosproject.evpnrouteservice.EvpnPrefix;
|
||||
import org.onosproject.evpnrouteservice.EvpnRoute;
|
||||
import org.onosproject.evpnrouteservice.EvpnRouteSet;
|
||||
import org.onosproject.evpnrouteservice.EvpnRouteStoreDelegate;
|
||||
import org.onosproject.evpnrouteservice.EvpnRouteTableId;
|
||||
import org.onosproject.evpnrouteservice.EvpnTable;
|
||||
import org.onosproject.evpnrouteservice.Label;
|
||||
import org.onosproject.evpnrouteservice.RouteDistinguisher;
|
||||
import org.onosproject.evpnrouteservice.VpnRouteTarget;
|
||||
import org.onosproject.store.serializers.KryoNamespaces;
|
||||
import org.onosproject.store.service.ConsistentMap;
|
||||
import org.onosproject.store.service.DistributedPrimitive;
|
||||
import org.onosproject.store.service.MapEvent;
|
||||
import org.onosproject.store.service.MapEventListener;
|
||||
import org.onosproject.store.service.Serializer;
|
||||
import org.onosproject.store.service.StorageService;
|
||||
import org.onosproject.store.service.Versioned;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Default implementation of a route table based on a consistent map.
|
||||
*/
|
||||
public class EvpnRouteTable implements EvpnTable {
|
||||
|
||||
private final EvpnRouteTableId id;
|
||||
private final ConsistentMap<EvpnPrefix, Set<EvpnRoute>> routes;
|
||||
private final EvpnRouteStoreDelegate delegate;
|
||||
private final ExecutorService executor;
|
||||
private final RouteTableListener listener = new RouteTableListener();
|
||||
|
||||
private final Consumer<DistributedPrimitive.Status> statusChangeListener;
|
||||
|
||||
/**
|
||||
* Creates a new route table.
|
||||
*
|
||||
* @param id route table ID
|
||||
* @param delegate route store delegate to notify of events
|
||||
* @param storageService storage service
|
||||
* @param executor executor service
|
||||
*/
|
||||
public EvpnRouteTable(EvpnRouteTableId id, EvpnRouteStoreDelegate delegate,
|
||||
StorageService storageService, ExecutorService executor) {
|
||||
this.delegate = checkNotNull(delegate);
|
||||
this.id = checkNotNull(id);
|
||||
this.routes = buildRouteMap(checkNotNull(storageService));
|
||||
this.executor = checkNotNull(executor);
|
||||
|
||||
statusChangeListener = status -> {
|
||||
if (status.equals(DistributedPrimitive.Status.ACTIVE)) {
|
||||
executor.execute(this::notifyExistingRoutes);
|
||||
}
|
||||
};
|
||||
routes.addStatusChangeListener(statusChangeListener);
|
||||
|
||||
notifyExistingRoutes();
|
||||
|
||||
routes.addListener(listener);
|
||||
}
|
||||
|
||||
private void notifyExistingRoutes() {
|
||||
routes.entrySet().stream()
|
||||
.map(e -> new EvpnInternalRouteEvent(
|
||||
EvpnInternalRouteEvent.Type.ROUTE_ADDED,
|
||||
new EvpnRouteSet(id, e.getKey(), e.getValue().value())))
|
||||
.forEach(delegate::notify);
|
||||
}
|
||||
|
||||
private ConsistentMap<EvpnPrefix, Set<EvpnRoute>> buildRouteMap(StorageService
|
||||
storageService) {
|
||||
KryoNamespace routeTableSerializer = KryoNamespace.newBuilder()
|
||||
.register(KryoNamespaces.API)
|
||||
.register(KryoNamespaces.MISC)
|
||||
.register(EvpnRoute.class)
|
||||
.register(EvpnPrefix.class)
|
||||
.register(RouteDistinguisher.class)
|
||||
.register(MacAddress.class)
|
||||
.register(IpPrefix.class)
|
||||
.register(EvpnRoute.Source.class)
|
||||
.register(IpAddress.class)
|
||||
.register(VpnRouteTarget.class)
|
||||
.register(Label.class)
|
||||
.register(EvpnRouteTableId.class)
|
||||
.build();
|
||||
return storageService.<EvpnPrefix, Set<EvpnRoute>>consistentMapBuilder()
|
||||
.withName("onos-evpn-routes-" + id.name())
|
||||
.withRelaxedReadConsistency()
|
||||
.withSerializer(Serializer.using(routeTableSerializer))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EvpnRouteTableId id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
routes.removeStatusChangeListener(statusChangeListener);
|
||||
routes.removeListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
shutdown();
|
||||
routes.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(EvpnRoute route) {
|
||||
routes.compute(route.evpnPrefix(), (prefix, set) -> {
|
||||
if (set == null) {
|
||||
set = new HashSet<>();
|
||||
}
|
||||
set.add(route);
|
||||
return set;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(EvpnRoute route) {
|
||||
routes.compute(route.evpnPrefix(), (prefix, set) -> {
|
||||
if (set != null) {
|
||||
set.remove(route);
|
||||
if (set.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return set;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<EvpnRouteSet> getRoutes() {
|
||||
return routes.entrySet().stream()
|
||||
.map(e -> new EvpnRouteSet(id, e.getKey(), e.getValue().value()))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public EvpnRouteSet getRoutes(EvpnPrefix prefix) {
|
||||
Versioned<Set<EvpnRoute>> routeSet = routes.get(prefix);
|
||||
|
||||
if (routeSet != null) {
|
||||
return new EvpnRouteSet(id, prefix, routeSet.value());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<EvpnRoute> getRoutesForNextHop(IpAddress nextHop) {
|
||||
// TODO index
|
||||
return routes.values().stream()
|
||||
.flatMap(v -> v.value().stream())
|
||||
.filter(r -> r.nextHop().equals(nextHop))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private class RouteTableListener
|
||||
implements MapEventListener<EvpnPrefix, Set<EvpnRoute>> {
|
||||
|
||||
private EvpnInternalRouteEvent createRouteEvent(
|
||||
EvpnInternalRouteEvent.Type type, MapEvent<EvpnPrefix, Set<EvpnRoute>>
|
||||
event) {
|
||||
Set<EvpnRoute> currentRoutes =
|
||||
(event.newValue() == null) ? Collections.emptySet() : event.newValue().value();
|
||||
return new EvpnInternalRouteEvent(type, new EvpnRouteSet(id, event
|
||||
.key(), currentRoutes));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void event(MapEvent<EvpnPrefix, Set<EvpnRoute>> event) {
|
||||
EvpnInternalRouteEvent ire = null;
|
||||
switch (event.type()) {
|
||||
case INSERT:
|
||||
ire = createRouteEvent(EvpnInternalRouteEvent.Type.ROUTE_ADDED, event);
|
||||
break;
|
||||
case UPDATE:
|
||||
if (event.newValue().value().size() > event.oldValue().value().size()) {
|
||||
ire = createRouteEvent(EvpnInternalRouteEvent.Type.ROUTE_ADDED, event);
|
||||
} else {
|
||||
ire = createRouteEvent(EvpnInternalRouteEvent.Type.ROUTE_REMOVED, event);
|
||||
}
|
||||
break;
|
||||
case REMOVE:
|
||||
ire = createRouteEvent(EvpnInternalRouteEvent.Type.ROUTE_REMOVED, event);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (ire != null) {
|
||||
delegate.notify(ire);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016-present Open Networking Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implementation of the unicast routing service.
|
||||
*/
|
||||
package org.onosproject.evpnrouteservice.store;
|
@ -1,28 +0,0 @@
|
||||
COMPILE_DEPS = CORE_DEPS + JACKSON + KRYO + CLI + [
|
||||
"//apps/tunnel/api:onos-apps-tunnel-api",
|
||||
"//core/store/serializers:onos-core-serializers",
|
||||
"//apps/gluon:onos-apps-gluon",
|
||||
"//apps/vtn/vtnrsc:onos-apps-vtn-vtnrsc",
|
||||
"//apps/route-service/api:onos-apps-route-service-api",
|
||||
"//apps/evpn-route-service/api:onos-apps-evpn-route-service-api",
|
||||
]
|
||||
|
||||
osgi_jar_with_tests(
|
||||
karaf_command_packages = ["org.onosproject.evpnopenflow.rsc.cli"],
|
||||
deps = COMPILE_DEPS,
|
||||
)
|
||||
|
||||
onos_app(
|
||||
category = "Traffic Engineering",
|
||||
description = "Ethernet VPN (EVPN) introduces a new model for Ethernet services delivery." +
|
||||
"It enables integrated Layer 2 service over Ethernet with multihoming.",
|
||||
required_apps = [
|
||||
"org.onosproject.route-service",
|
||||
"org.onosproject.evpn-route-service",
|
||||
"org.onosproject.gluon",
|
||||
"org.onosproject.tunnel",
|
||||
"org.onosproject.vtn",
|
||||
],
|
||||
title = "EVPN OpenFlow",
|
||||
url = "http://onosproject.org",
|
||||
)
|
@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.manager;
|
||||
|
||||
import org.onosproject.evpnopenflow.rsc.VpnPort;
|
||||
import org.onosproject.evpnrouteservice.EvpnRoute;
|
||||
import org.onosproject.net.Host;
|
||||
|
||||
/**
|
||||
* Service for interacting with the route and host events.
|
||||
*/
|
||||
public interface EvpnService {
|
||||
/**
|
||||
* Transfer remote route to private route and set mpls flows out when
|
||||
* BgpRoute update.
|
||||
*
|
||||
* @param route evpn route
|
||||
*/
|
||||
void onBgpEvpnRouteUpdate(EvpnRoute route);
|
||||
|
||||
/**
|
||||
* Transfer remote route to private route and delete mpls flows out when
|
||||
* BgpRoute delete.
|
||||
*
|
||||
* @param route evpn route
|
||||
*/
|
||||
void onBgpEvpnRouteDelete(EvpnRoute route);
|
||||
|
||||
/**
|
||||
* Get VPN info from EVPN app store and create route, set flows when host
|
||||
* detected.
|
||||
*
|
||||
* @param host host information
|
||||
*/
|
||||
void onHostDetected(Host host);
|
||||
|
||||
/**
|
||||
* Get VPN info from EVPN app store and delete route, set flows when
|
||||
* host
|
||||
* vanished.
|
||||
*
|
||||
* @param host host information
|
||||
*/
|
||||
void onHostVanished(Host host);
|
||||
|
||||
/**
|
||||
* Get VPN info from EVPN app store and create route, set flows when
|
||||
* host
|
||||
* detected.
|
||||
*
|
||||
* @param vpnPort vpnPort information
|
||||
*/
|
||||
void onVpnPortSet(VpnPort vpnPort);
|
||||
|
||||
/**
|
||||
* Get VPN info from EVPN app store and delete route, set flows when host
|
||||
* vanished.
|
||||
*
|
||||
* @param vpnPort vpnPort information
|
||||
*/
|
||||
void onVpnPortDelete(VpnPort vpnPort);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* EVPN application that process configuration and host, vpn-port, route
|
||||
* events.
|
||||
*/
|
||||
package org.onosproject.evpnopenflow.manager.impl;
|
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* EVPN application that process configuration and host, vpn-port, route
|
||||
* events.
|
||||
*/
|
||||
package org.onosproject.evpnopenflow.manager;
|
@ -1,163 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc;
|
||||
|
||||
import org.onlab.packet.MacAddress;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.vtnrsc.AllowedAddressPair;
|
||||
import org.onosproject.vtnrsc.BindingHostId;
|
||||
import org.onosproject.vtnrsc.FixedIp;
|
||||
import org.onosproject.vtnrsc.SecurityGroup;
|
||||
import org.onosproject.vtnrsc.TenantId;
|
||||
import org.onosproject.vtnrsc.TenantNetworkId;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Representation of a Base port.
|
||||
*/
|
||||
public interface BasePort {
|
||||
/**
|
||||
* Coarse classification of the type of the virtual port.
|
||||
*/
|
||||
enum State {
|
||||
/**
|
||||
* Signifies that a basePort is currently active,This state mean that
|
||||
* this basePort is available.
|
||||
*/
|
||||
ACTIVE,
|
||||
/**
|
||||
* Signifies that a basePort is currently unavailable.
|
||||
*/
|
||||
DOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the basePort identifier.
|
||||
*
|
||||
* @return basePort identifier
|
||||
*/
|
||||
BasePortId portId();
|
||||
|
||||
/**
|
||||
* Returns the network identifier.
|
||||
*
|
||||
* @return tenantNetwork identifier
|
||||
*/
|
||||
TenantNetworkId networkId();
|
||||
|
||||
/**
|
||||
* Returns the symbolic name for the basePort.
|
||||
*
|
||||
* @return basePort name
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Returns the administrative status of the port,which is up(true) or
|
||||
* down(false).
|
||||
*
|
||||
* @return true if the administrative status of the port is up
|
||||
*/
|
||||
boolean adminStateUp();
|
||||
|
||||
/**
|
||||
* Returns the state.
|
||||
*
|
||||
* @return state
|
||||
*/
|
||||
String state();
|
||||
|
||||
/**
|
||||
* Returns the MAC address.
|
||||
*
|
||||
* @return MAC Address
|
||||
*/
|
||||
MacAddress macAddress();
|
||||
|
||||
/**
|
||||
* Returns the port tenantId.
|
||||
*
|
||||
* @return port tenantId
|
||||
*/
|
||||
TenantId tenantId();
|
||||
|
||||
/**
|
||||
* Returns the device identifier.
|
||||
*
|
||||
* @return deviceId
|
||||
*/
|
||||
DeviceId deviceId();
|
||||
|
||||
/**
|
||||
* Returns the identifier of the entity that uses this port.
|
||||
*
|
||||
* @return deviceOwner
|
||||
*/
|
||||
String deviceOwner();
|
||||
|
||||
/**
|
||||
* Returns the basePort allowedAddressPairs.
|
||||
*
|
||||
* @return basePort allowedAddressPairs
|
||||
*/
|
||||
Collection<AllowedAddressPair> allowedAddressPairs();
|
||||
|
||||
/**
|
||||
* Returns set of IP addresses for the port, include the IP addresses and subnet
|
||||
* identity.
|
||||
*
|
||||
* @return FixedIps Set of fixedIp
|
||||
*/
|
||||
Set<FixedIp> fixedIps();
|
||||
|
||||
/**
|
||||
* Returns the basePort bindinghostId.
|
||||
*
|
||||
* @return basePort bindinghostId
|
||||
*/
|
||||
BindingHostId bindingHostId();
|
||||
|
||||
/**
|
||||
* Returns the basePort bindingVnicType.
|
||||
*
|
||||
* @return basePort bindingVnicType
|
||||
*/
|
||||
String bindingVnicType();
|
||||
|
||||
/**
|
||||
* Returns the basePort bindingVifType.
|
||||
*
|
||||
* @return basePort bindingVifType
|
||||
*/
|
||||
String bindingVifType();
|
||||
|
||||
/**
|
||||
* Returns the basePort bindingvifDetail.
|
||||
*
|
||||
* @return basePort bindingvifDetail
|
||||
*/
|
||||
String bindingVifDetails();
|
||||
|
||||
/**
|
||||
* Returns the security groups.
|
||||
*
|
||||
* @return port security groups
|
||||
*/
|
||||
Iterable<SecurityGroup> securityGroups();
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc;
|
||||
|
||||
import org.onlab.util.Identifier;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Immutable representation of a base port identifier.
|
||||
*/
|
||||
public final class BasePortId extends Identifier<String> {
|
||||
// Public construction is prohibited
|
||||
private BasePortId(String basePortId) {
|
||||
super(checkNotNull(basePortId, "BasePortId cannot be null"));
|
||||
}
|
||||
|
||||
public String portId() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a virtualPort id using the supplied portId.
|
||||
*
|
||||
* @param portId baseport identifier
|
||||
* @return BasePortId
|
||||
*/
|
||||
public static BasePortId portId(String portId) {
|
||||
return new BasePortId(portId);
|
||||
}
|
||||
}
|
@ -1,236 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc;
|
||||
|
||||
import org.onlab.packet.MacAddress;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.vtnrsc.AllowedAddressPair;
|
||||
import org.onosproject.vtnrsc.BindingHostId;
|
||||
import org.onosproject.vtnrsc.FixedIp;
|
||||
import org.onosproject.vtnrsc.SecurityGroup;
|
||||
import org.onosproject.vtnrsc.TenantId;
|
||||
import org.onosproject.vtnrsc.TenantNetworkId;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
|
||||
/**
|
||||
* Default implementation of Base port.
|
||||
*/
|
||||
public final class DefaultBasePort implements BasePort {
|
||||
private final BasePortId id;
|
||||
private final TenantNetworkId networkId;
|
||||
private final Boolean adminStateUp;
|
||||
private final String name;
|
||||
private final String state;
|
||||
private final MacAddress macAddress;
|
||||
private final TenantId tenantId;
|
||||
private final String deviceOwner;
|
||||
private final DeviceId deviceId;
|
||||
private final Set<FixedIp> fixedIps;
|
||||
private final BindingHostId bindingHostId;
|
||||
private final String bindingVnicType;
|
||||
private final String bindingVifType;
|
||||
private final String bindingVifDetails;
|
||||
private final Set<AllowedAddressPair> allowedAddressPairs;
|
||||
private final Set<SecurityGroup> securityGroups;
|
||||
|
||||
/**
|
||||
* Creates a BasePort object.
|
||||
*
|
||||
* @param id the base port identifier
|
||||
* @param networkId the network identifier
|
||||
* @param adminStateUp adminStateup true or false
|
||||
* @param strMap the map of properties of base port
|
||||
* @param state base port state
|
||||
* @param macAddress the MAC address
|
||||
* @param tenantId the tenant identifier
|
||||
* @param deviceId the device identifier
|
||||
* @param fixedIps set of fixed IP
|
||||
* @param bindingHostId the binding host identifier
|
||||
* @param allowedAddressPairs the collection of allowdeAddressPairs
|
||||
* @param securityGroups the collection of securityGroups
|
||||
*/
|
||||
public DefaultBasePort(BasePortId id,
|
||||
TenantNetworkId networkId,
|
||||
Boolean adminStateUp,
|
||||
Map<String, String> strMap,
|
||||
String state,
|
||||
MacAddress macAddress,
|
||||
TenantId tenantId,
|
||||
DeviceId deviceId,
|
||||
Set<FixedIp> fixedIps,
|
||||
BindingHostId bindingHostId,
|
||||
Set<AllowedAddressPair> allowedAddressPairs,
|
||||
Set<SecurityGroup> securityGroups) {
|
||||
this.id = id;
|
||||
this.networkId = networkId;
|
||||
this.adminStateUp = adminStateUp;
|
||||
this.name = strMap.get("name");
|
||||
this.state = state;
|
||||
this.macAddress = macAddress;
|
||||
this.tenantId = tenantId;
|
||||
this.deviceOwner = strMap.get("deviceOwner");
|
||||
this.deviceId = deviceId;
|
||||
this.fixedIps = fixedIps;
|
||||
this.bindingHostId = bindingHostId;
|
||||
this.bindingVnicType = strMap.get("bindingVnicType");
|
||||
this.bindingVifType = strMap.get("bindingVifType");
|
||||
this.bindingVifDetails = strMap.get("bindingVifDetails");
|
||||
this.allowedAddressPairs = allowedAddressPairs;
|
||||
this.securityGroups = securityGroups;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasePortId portId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TenantNetworkId networkId() {
|
||||
return networkId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean adminStateUp() {
|
||||
return adminStateUp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String state() {
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MacAddress macAddress() {
|
||||
return macAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TenantId tenantId() {
|
||||
return tenantId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceId deviceId() {
|
||||
return deviceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deviceOwner() {
|
||||
return deviceOwner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<AllowedAddressPair> allowedAddressPairs() {
|
||||
return allowedAddressPairs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<FixedIp> fixedIps() {
|
||||
return fixedIps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BindingHostId bindingHostId() {
|
||||
return bindingHostId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String bindingVnicType() {
|
||||
return bindingVifType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String bindingVifType() {
|
||||
return bindingVifType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String bindingVifDetails() {
|
||||
return bindingVifDetails;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SecurityGroup> securityGroups() {
|
||||
return securityGroups;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, networkId, adminStateUp, name, state,
|
||||
macAddress, tenantId, deviceId, deviceOwner,
|
||||
allowedAddressPairs, fixedIps, bindingHostId,
|
||||
bindingVnicType, bindingVifType, bindingVifDetails,
|
||||
securityGroups);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof DefaultBasePort) {
|
||||
final DefaultBasePort that = (DefaultBasePort) obj;
|
||||
return Objects.equals(this.id, that.id)
|
||||
&& Objects.equals(this.networkId, that.networkId)
|
||||
&& Objects.equals(this.adminStateUp, that.adminStateUp)
|
||||
&& Objects.equals(this.state, that.state)
|
||||
&& Objects.equals(this.name, that.name)
|
||||
&& Objects.equals(this.tenantId, that.tenantId)
|
||||
&& Objects.equals(this.macAddress, that.macAddress)
|
||||
&& Objects.equals(this.deviceId, that.deviceId)
|
||||
&& Objects.equals(this.deviceOwner, that.deviceOwner)
|
||||
&& Objects.equals(this.allowedAddressPairs,
|
||||
that.allowedAddressPairs)
|
||||
&& Objects.equals(this.fixedIps, that.fixedIps)
|
||||
&& Objects.equals(this.bindingHostId, that.bindingHostId)
|
||||
&& Objects.equals(this.bindingVifDetails,
|
||||
that.bindingVifDetails)
|
||||
&& Objects.equals(this.bindingVifType, that.bindingVifType)
|
||||
&& Objects.equals(this.bindingVnicType,
|
||||
that.bindingVnicType)
|
||||
&& Objects.equals(this.securityGroups, that.securityGroups);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this).add("id", id).add("network_id", networkId)
|
||||
.add("adminStateUp", adminStateUp).add("state", state)
|
||||
.add("name", name).add("state", state)
|
||||
.add("macAddress", macAddress).add("tenantId", tenantId)
|
||||
.add("deviced", deviceId).add("deviceOwner", deviceOwner)
|
||||
.add("allowedAddressPairs", allowedAddressPairs)
|
||||
.add("fixedIp", fixedIps).add("bindingHostId", bindingHostId)
|
||||
.add("bindingVnicType", bindingVnicType)
|
||||
.add("bindingVifDetails", bindingVifDetails)
|
||||
.add("bindingVifType", bindingVifType)
|
||||
.add("securityGroups", securityGroups).toString();
|
||||
}
|
||||
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc;
|
||||
|
||||
import org.onosproject.evpnrouteservice.VpnRouteTarget;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ID_CANNOT_BE_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.RT_CANNOT_BE_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.RT_TYPE_CANNOT_BE_NULL;
|
||||
|
||||
/**
|
||||
* Default implementation of VPN AF configuration.
|
||||
*/
|
||||
public class DefaultVpnAfConfig implements VpnAfConfig {
|
||||
|
||||
private final String exportRoutePolicy;
|
||||
private final String importRoutePolicy;
|
||||
private final VpnRouteTarget routeTarget;
|
||||
private final String routeTargetType;
|
||||
|
||||
/**
|
||||
* creates vpn af configuration object.
|
||||
*
|
||||
* @param exportRoutePolicy export route policy
|
||||
* @param importRoutePolicy import route policy
|
||||
* @param routeTarget route target value
|
||||
* @param routeTargetType route target type
|
||||
*/
|
||||
public DefaultVpnAfConfig(String exportRoutePolicy,
|
||||
String importRoutePolicy,
|
||||
VpnRouteTarget routeTarget,
|
||||
String routeTargetType) {
|
||||
this.exportRoutePolicy = checkNotNull(exportRoutePolicy,
|
||||
ID_CANNOT_BE_NULL);
|
||||
this.importRoutePolicy = checkNotNull(importRoutePolicy,
|
||||
ID_CANNOT_BE_NULL);
|
||||
this.routeTarget = checkNotNull(routeTarget, RT_CANNOT_BE_NULL);
|
||||
this.routeTargetType = checkNotNull(routeTargetType,
|
||||
RT_TYPE_CANNOT_BE_NULL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String exportRoutePolicy() {
|
||||
return exportRoutePolicy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String importRoutePolicy() {
|
||||
return importRoutePolicy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VpnRouteTarget routeTarget() {
|
||||
return routeTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String routeTargetType() {
|
||||
return routeTargetType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this)
|
||||
.add("exportRoutePolicy", exportRoutePolicy)
|
||||
.add("importRoutePolicy", importRoutePolicy)
|
||||
.add("routeTarget", routeTarget)
|
||||
.add("routeTargetType", routeTargetType)
|
||||
.toString();
|
||||
}
|
||||
}
|
@ -1,153 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc;
|
||||
|
||||
import org.onosproject.evpnrouteservice.EvpnInstanceName;
|
||||
import org.onosproject.evpnrouteservice.RouteDistinguisher;
|
||||
import org.onosproject.evpnrouteservice.VpnRouteTarget;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.CONFIG_RT_CANNOT_BE_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.DESCRIPTION;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.DESCRIPTION_CANNOT_BE_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EXPORT_RT_CANNOT_BE_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ID;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ID_CANNOT_BE_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.IMPORT_RT_CANNOT_BE_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.INSTANCE_NAME_CANNOT_BE_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.RD_CANNOT_BE_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ROUTE_DISTINGUISHER;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPNINSTANCE_NAME;
|
||||
|
||||
/**
|
||||
* Default implementation of VPN instance.
|
||||
*/
|
||||
public class DefaultVpnInstance implements VpnInstance {
|
||||
private final VpnInstanceId id;
|
||||
private final String description;
|
||||
private final EvpnInstanceName name;
|
||||
private final RouteDistinguisher routeDistinguisher;
|
||||
private final Set<VpnRouteTarget> exportRtSet;
|
||||
private final Set<VpnRouteTarget> importRtSet;
|
||||
private final Set<VpnRouteTarget> configRtSet;
|
||||
|
||||
|
||||
/**
|
||||
* creates vpn instance object.
|
||||
*
|
||||
* @param id vpn instance identifier
|
||||
* @param instanceName the name of vpn instance
|
||||
* @param description the description of vpn instance
|
||||
* @param routeDistinguisher the routeDistinguisher of vpn instance
|
||||
* @param exportRtSet the export route target information
|
||||
* @param importRtSet the import route target information
|
||||
* @param configRtSet the config route target information
|
||||
*/
|
||||
public DefaultVpnInstance(VpnInstanceId id, EvpnInstanceName instanceName,
|
||||
String description,
|
||||
RouteDistinguisher routeDistinguisher,
|
||||
Set<VpnRouteTarget> exportRtSet,
|
||||
Set<VpnRouteTarget> importRtSet,
|
||||
Set<VpnRouteTarget> configRtSet) {
|
||||
this.id = checkNotNull(id, ID_CANNOT_BE_NULL);
|
||||
this.name = checkNotNull(instanceName, INSTANCE_NAME_CANNOT_BE_NULL);
|
||||
this.description = checkNotNull(description,
|
||||
DESCRIPTION_CANNOT_BE_NULL);
|
||||
this.routeDistinguisher = checkNotNull(routeDistinguisher,
|
||||
RD_CANNOT_BE_NULL);
|
||||
this.exportRtSet = checkNotNull(exportRtSet, EXPORT_RT_CANNOT_BE_NULL);
|
||||
this.importRtSet = checkNotNull(importRtSet, IMPORT_RT_CANNOT_BE_NULL);
|
||||
this.configRtSet = checkNotNull(configRtSet, CONFIG_RT_CANNOT_BE_NULL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VpnInstanceId id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RouteDistinguisher routeDistinguisher() {
|
||||
return routeDistinguisher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EvpnInstanceName vpnInstanceName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<VpnRouteTarget> getExportRouteTargets() {
|
||||
return exportRtSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<VpnRouteTarget> getImportRouteTargets() {
|
||||
return importRtSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<VpnRouteTarget> getConfigRouteTargets() {
|
||||
return configRtSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, name, description, routeDistinguisher,
|
||||
exportRtSet, importRtSet, configRtSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof DefaultVpnInstance) {
|
||||
final DefaultVpnInstance that = (DefaultVpnInstance) obj;
|
||||
return Objects.equals(this.id, that.id)
|
||||
&& Objects.equals(this.name, that.name)
|
||||
&& Objects.equals(this.description, that.description)
|
||||
&& Objects.equals(this.routeDistinguisher,
|
||||
that.routeDistinguisher)
|
||||
&& Objects.equals(this.exportRtSet, that.exportRtSet)
|
||||
&& Objects.equals(this.importRtSet, that.importRtSet)
|
||||
&& Objects.equals(this.configRtSet, that.configRtSet);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this)
|
||||
.add(ID, id)
|
||||
.add(DESCRIPTION, description)
|
||||
.add(VPNINSTANCE_NAME, name)
|
||||
.add(ROUTE_DISTINGUISHER, routeDistinguisher)
|
||||
.add("exportRtSet", exportRtSet)
|
||||
.add("importRtSet", importRtSet)
|
||||
.add("configRtSet", configRtSet)
|
||||
.toString();
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ID;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ID_CANNOT_BE_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_ID;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_ID_CANNOT_BE_NULL;
|
||||
|
||||
/**
|
||||
* Default implementation of VPN port.
|
||||
*/
|
||||
public class DefaultVpnPort implements VpnPort {
|
||||
|
||||
private final VpnPortId id;
|
||||
private final VpnInstanceId vpnInstanceId;
|
||||
|
||||
/**
|
||||
* creates vpn port object.
|
||||
*
|
||||
* @param id vpn port id
|
||||
* @param vpnInstanceId vpn instance id
|
||||
*/
|
||||
public DefaultVpnPort(VpnPortId id, VpnInstanceId vpnInstanceId) {
|
||||
this.id = checkNotNull(id, ID_CANNOT_BE_NULL);
|
||||
this.vpnInstanceId = checkNotNull(vpnInstanceId,
|
||||
VPN_INSTANCE_ID_CANNOT_BE_NULL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VpnPortId id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VpnInstanceId vpnInstanceId() {
|
||||
return vpnInstanceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, vpnInstanceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof DefaultVpnPort) {
|
||||
final DefaultVpnPort that = (DefaultVpnPort) obj;
|
||||
return Objects.equals(this.id, that.id)
|
||||
&& Objects.equals(this.vpnInstanceId, that.vpnInstanceId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper(this).add(ID, id)
|
||||
.add(VPN_INSTANCE_ID, vpnInstanceId).toString();
|
||||
}
|
||||
}
|
@ -1,186 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc;
|
||||
|
||||
/**
|
||||
* Provides constants used in EVPN openflow application.
|
||||
*/
|
||||
public final class EvpnConstants {
|
||||
private EvpnConstants() {
|
||||
}
|
||||
|
||||
public static final String APP_ID = "org.onosproject.evpnopenflow";
|
||||
public static final String EVPN_OPENFLOW_START = "evpn-openflow app is " +
|
||||
"started";
|
||||
public static final String EVPN_OPENFLOW_STOP = "evpn-openflow app is " +
|
||||
"stopped";
|
||||
public static final String EVPN_VPN_PORT_START = "EVPN port started";
|
||||
public static final String EVPN_VPN_PORT_STOP = "EVPN port stopped";
|
||||
public static final String EVPN_VPN_INSTANCE_START = "EVPN instance " +
|
||||
"started";
|
||||
public static final String EVPN_VPN_INSTANCE_STOP = "EVPN instance " +
|
||||
"stopped";
|
||||
public static final String HOST_DETECT = "Host detected {}";
|
||||
public static final String HOST_VANISHED = "Host vanished {}";
|
||||
public static final String IFACEID = "ifaceid";
|
||||
public static final String IFACEID_OF_HOST_IS_NULL =
|
||||
"The ifaceId of host is null";
|
||||
public static final String CANT_FIND_VPN_PORT = "Can't find vpnport {}";
|
||||
public static final String CANT_FIND_VPN_INSTANCE = "EVPN instance {} is " +
|
||||
"not exist";
|
||||
public static final String CANT_FIND_CONTROLLER_DEVICE = "Can't find " +
|
||||
"controller of device: {}";
|
||||
public static final String GET_PRIVATE_LABEL = "Get private label {}";
|
||||
public static final String RELEASE_LABEL_FAILED = "Release resoure label " +
|
||||
"{} failed";
|
||||
public static final String VPN_PORT_UNBIND = "On EVPN port unbind";
|
||||
public static final String VPN_PORT_BIND = "On EVPN port bind";
|
||||
public static final String SLASH = "/";
|
||||
public static final String COMMA = ",";
|
||||
public static final String VPN_INSTANCE_TARGET = "VpnService";
|
||||
public static final String VPN_PORT_TARGET = "VpnBinding";
|
||||
public static final String BASEPORT = "Port";
|
||||
public static final String VPN_AF_TARGET = "VpnAfConfig";
|
||||
public static final String BGP_PEERING = "BGPPeering";
|
||||
public static final String DATA_PLANE_TUNNEL = "DataplaneTunnel";
|
||||
public static final String VPN_PORT_STORE = "evpn-port-store";
|
||||
public static final String BASE_PORT_STORE = "evpn-baseport-store";
|
||||
public static final String VPN_INSTANCE_STORE =
|
||||
"evpn-instance-store";
|
||||
public static final String VPN_PORT_ID_NOT_NULL = "EVPN port ID cannot be" +
|
||||
" null";
|
||||
public static final String VPN_PORT_NOT_NULL = "EVPN port cannot be null";
|
||||
public static final String RESPONSE_NOT_NULL = "JsonNode can not be null";
|
||||
public static final String LISTENER_NOT_NULL = "Listener cannot be null";
|
||||
public static final String EVENT_NOT_NULL = "Event cannot be null";
|
||||
public static final String DELETE = "delete";
|
||||
public static final String SET = "set";
|
||||
public static final String UPDATE = "update";
|
||||
public static final String VPN_PORT_ID = "EVPN port ID is {} ";
|
||||
public static final String VPN_PORT_CREATION_FAILED = "The EVPN port " +
|
||||
"creation is failed whose identifier is {} ";
|
||||
public static final String VPN_PORT_IS_NOT_EXIST = "The EVPN port is not " +
|
||||
"exist whose identifier is {}";
|
||||
public static final String VPN_PORT_UPDATE_FAILED = "The EVPN port update" +
|
||||
" is failed whose identifier is {}";
|
||||
public static final String VPN_PORT_DELETE_FAILED =
|
||||
"The EVPN port delete is failed whose identifier is {}";
|
||||
public static final String INTERFACE_ID = "interface_id";
|
||||
public static final String ID = "id";
|
||||
public static final String VPN_INSTANCE = "service_id";
|
||||
public static final String VPN_INSTANCE_ID_NOT_NULL = "EVPN instance ID " +
|
||||
"cannot be null";
|
||||
public static final String VPN_INSTANCE_NOT_NULL = "EVPN instance cannot " +
|
||||
"be null";
|
||||
public static final String JSON_NOT_NULL = "JsonNode can not be null";
|
||||
public static final String INSTANCE_ID = "EVPN instance ID is {} ";
|
||||
public static final String VPN_INSTANCE_CREATION_FAILED = "The " +
|
||||
"EVPN instance creation is failed whose identifier is {} ";
|
||||
public static final String VPN_INSTANCE_IS_NOT_EXIST = "The EVPN instance" +
|
||||
" is not exist whose identifier is {}";
|
||||
public static final String VPN_INSTANCE_UPDATE_FAILED = "The EVPN " +
|
||||
"instance update is failed whose identifier is {}";
|
||||
public static final String VPN_INSTANCE_DELETE_FAILED = "The EVPN " +
|
||||
"instance delete is failed whose identifier is {}";
|
||||
public static final String VPN_INSTANCE_NAME = "name";
|
||||
public static final String DESCRIPTION = "description";
|
||||
public static final String ROUTE_DISTINGUISHERS = "route_distinguishers";
|
||||
public static final String IPV4_FAMILY = "ipv4_family";
|
||||
static final String ID_CANNOT_BE_NULL = "ID cannot be null";
|
||||
static final String INSTANCE_NAME_CANNOT_BE_NULL = "Instance name cannot " +
|
||||
"be null";
|
||||
static final String DESCRIPTION_CANNOT_BE_NULL = "Description cannot be " +
|
||||
"null";
|
||||
static final String RD_CANNOT_BE_NULL = "RouteDistinguisher cannot be null";
|
||||
static final String RT_CANNOT_BE_NULL = "RouteTarget cannot be null";
|
||||
static final String VPNINSTANCE_NAME = "vpnInstanceName";
|
||||
static final String ROUTE_DISTINGUISHER = "routeDistinguisher";
|
||||
static final String VPN_INSTANCE_ID_CANNOT_BE_NULL = "EVPN instance ID " +
|
||||
"cannot be null";
|
||||
static final String VPN_INSTANCE_ID = "vpnInstanceId";
|
||||
public static final String FORMAT_VPN_INSTANCE = "Id=%s, description=%s,"
|
||||
+ " name=%s, routeDistinguisher=%s, routeTarget=%s";
|
||||
public static final String FORMAT_VPN_PORT = " EVPN port id=%-32s, " +
|
||||
"EVPN instance id=%-18s";
|
||||
public static final String FORMAT_PRIVATE_ROUTE = " %-18s %-15s %-10s";
|
||||
public static final String FORMAT_PUBLIC_ROUTE = " %-18s %-18s %-10s";
|
||||
public static final String SWITCH_CHANNEL_ID = "channelId";
|
||||
public static final String NOT_MASTER_FOR_SPECIFIC_DEVICE = "The local " +
|
||||
"controller is not master for the specified deviceId";
|
||||
public static final String VPN_AF_CONFIG_STORE =
|
||||
"evpn-vpn-af-config-store";
|
||||
public static final String EVPN_VPN_AF_CONFIG_START = "EVPN af config" +
|
||||
" started";
|
||||
public static final String EVPN_VPN_AF_CONFIG_STOP = "EVPN af config" +
|
||||
" stopped";
|
||||
static final String RT_TYPE_CANNOT_BE_NULL = "Route target type " +
|
||||
"cannot be null";
|
||||
public static final String VPN_AF_CONFIG_NOT_NULL = "EVPN af config be " +
|
||||
"null";
|
||||
public static final String ROUTE_TARGET_VALUE = "Route target value is {} ";
|
||||
public static final String VPN_AF_CONFIG_CREATION_FAILED = "The " +
|
||||
"EVPN af config creation is failed whose route target is {} ";
|
||||
public static final String VPN_AF_CONFIG_UPDATE_FAILED = "The EVPN af " +
|
||||
"config update is failed whose identifier is {}";
|
||||
public static final String VPN_AF_CONFIG_IS_NOT_EXIST = "The EVPN AF " +
|
||||
"config is not exist whose identifier is {}";
|
||||
public static final String ROUTE_TARGET_CANNOT_NOT_NULL = "Route target " +
|
||||
"value cannot be null";
|
||||
public static final String ROUTE_TARGET_DELETE_FAILED = "The route target" +
|
||||
" delete is failed whose route target value is {}";
|
||||
static final String EXPORT_RT_CANNOT_BE_NULL = "export route " +
|
||||
"target set cannot be null";
|
||||
static final String IMPORT_RT_CANNOT_BE_NULL = "import route " +
|
||||
"target set cannot be null";
|
||||
static final String CONFIG_RT_CANNOT_BE_NULL = "import route " +
|
||||
"target set cannot be null";
|
||||
public static final String EXPORT_EXTCOMMUNITY = "export_extcommunity";
|
||||
public static final String IMPORT_EXTCOMMUNITY = "import_extcommunity";
|
||||
public static final String BOTH = "both";
|
||||
public static final String INVALID_ROUTE_TARGET_TYPE
|
||||
= "Invalid route target type has received";
|
||||
public static final String INVALID_EVENT_RECEIVED
|
||||
= "Invalid event is received while processing network " +
|
||||
"configuration event";
|
||||
public static final String NETWORK_CONFIG_EVENT_IS_RECEIVED
|
||||
= "Event is received from network configuration {}";
|
||||
public static final int ARP_PRIORITY = 0xffff;
|
||||
public static final short ARP_RESPONSE = 0x2;
|
||||
public static final String INVALID_TARGET_RECEIVED
|
||||
= "Invalid target type has received";
|
||||
public static final String INVALID_ACTION_VPN_AF_CONFIG
|
||||
= "Invalid action is received while processing VPN af" +
|
||||
" configuration";
|
||||
public static final String EXPORT_ROUTE_POLICY = "export_route_policy";
|
||||
public static final String IMPORT_ROUTE_POLICY = "import_route_policy";
|
||||
public static final String VRF_RT_TYPE = "vrf_rt_type";
|
||||
public static final String VRF_RT_VALUE = "vrf_rt_value";
|
||||
public static final String BGP_EVPN_ROUTE_UPDATE_START
|
||||
= "bgp evpn route update start {}";
|
||||
public static final String MPLS_OUT_FLOWS = "mpls out flows --> {}";
|
||||
public static final String BGP_EVPN_ROUTE_DELETE_START
|
||||
= "bgp route delete start {}";
|
||||
public static final String ROUTE_ADD_ARP_RULES = "Route ARP Rules-->ADD";
|
||||
public static final String ROUTE_REMOVE_ARP_RULES
|
||||
= "Route ARP Rules-->REMOVE";
|
||||
public static final String TUNNEL_DST = "tunnelDst";
|
||||
public static final String FAILED_TO_SET_TUNNEL_DST
|
||||
= "Failed to get extension instruction to set tunnel dst {}";
|
||||
public static final String VXLAN = "vxlan";
|
||||
public static final String CANNOT_FIND_TUNNEL_PORT_DEVICE =
|
||||
"Can't find tunnel port in device {}";
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc;
|
||||
|
||||
import org.onosproject.evpnrouteservice.VpnRouteTarget;
|
||||
|
||||
/**
|
||||
* Representation of a VPN af configuration.
|
||||
*/
|
||||
public interface VpnAfConfig {
|
||||
|
||||
/**
|
||||
* Returns the export route policy information.
|
||||
*
|
||||
* @return export route policy
|
||||
*/
|
||||
String exportRoutePolicy();
|
||||
|
||||
/**
|
||||
* Returns the import route policy information.
|
||||
*
|
||||
* @return export route policy
|
||||
*/
|
||||
String importRoutePolicy();
|
||||
|
||||
/**
|
||||
* Returns the route target value.
|
||||
*
|
||||
* @return route target value
|
||||
*/
|
||||
VpnRouteTarget routeTarget();
|
||||
|
||||
/**
|
||||
* Returns the route target type.
|
||||
*
|
||||
* @return route target type
|
||||
*/
|
||||
String routeTargetType();
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc;
|
||||
|
||||
import org.onosproject.evpnrouteservice.EvpnInstanceName;
|
||||
import org.onosproject.evpnrouteservice.RouteDistinguisher;
|
||||
import org.onosproject.evpnrouteservice.VpnRouteTarget;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Representation of a VPN instance.
|
||||
*/
|
||||
public interface VpnInstance {
|
||||
|
||||
/**
|
||||
* Returns the VPN instance identifier.
|
||||
*
|
||||
* @return VPN instance identifier
|
||||
*/
|
||||
VpnInstanceId id();
|
||||
|
||||
/**
|
||||
* Returns the VPN instance description.
|
||||
*
|
||||
* @return VPN instance description
|
||||
*/
|
||||
String description();
|
||||
|
||||
/**
|
||||
* Returns the VPN instance route distinguishes.
|
||||
*
|
||||
* @return VPN instance route distinguishes
|
||||
*/
|
||||
RouteDistinguisher routeDistinguisher();
|
||||
|
||||
/**
|
||||
* Returns the VPN instance name.
|
||||
*
|
||||
* @return VPN instance name
|
||||
*/
|
||||
EvpnInstanceName vpnInstanceName();
|
||||
|
||||
/**
|
||||
* Returns the export route target information.
|
||||
*
|
||||
* @return export route target information
|
||||
*/
|
||||
Set<VpnRouteTarget> getExportRouteTargets();
|
||||
|
||||
/**
|
||||
* Returns the import route target information.
|
||||
*
|
||||
* @return VPN instance ipv4 family
|
||||
*/
|
||||
Set<VpnRouteTarget> getImportRouteTargets();
|
||||
|
||||
/**
|
||||
* Returns the config route target information.
|
||||
*
|
||||
* @return config route target information.
|
||||
*/
|
||||
Set<VpnRouteTarget> getConfigRouteTargets();
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc;
|
||||
|
||||
import org.onlab.util.Identifier;
|
||||
|
||||
/**
|
||||
* Immutable representation of a VPN instance identity.
|
||||
*/
|
||||
public final class VpnInstanceId extends Identifier<String> {
|
||||
// Public construction is prohibited
|
||||
private VpnInstanceId(String vpnInstanceId) {
|
||||
super(vpnInstanceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a VPN instance identifier.
|
||||
*
|
||||
* @param vpnInstanceId VPN instance identify string
|
||||
* @return VPN instance identifier
|
||||
*/
|
||||
public static VpnInstanceId vpnInstanceId(String vpnInstanceId) {
|
||||
return new VpnInstanceId(vpnInstanceId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns VPN instance identifier.
|
||||
*
|
||||
* @return the VPN instance identifier
|
||||
*/
|
||||
public String vpnInstanceId() {
|
||||
return identifier;
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc;
|
||||
|
||||
/**
|
||||
* Representation of a VPN port.
|
||||
*/
|
||||
public interface VpnPort {
|
||||
|
||||
/**
|
||||
* Returns the VPN port identifier.
|
||||
*
|
||||
* @return VPN port identifier
|
||||
*/
|
||||
VpnPortId id();
|
||||
|
||||
/**
|
||||
* Returns the VPN instance identifier.
|
||||
*
|
||||
* @return VPN instance identifier
|
||||
*/
|
||||
VpnInstanceId vpnInstanceId();
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc;
|
||||
|
||||
import org.onlab.util.Identifier;
|
||||
|
||||
/**
|
||||
* Immutable representation of a VPN port identity.
|
||||
*/
|
||||
public final class VpnPortId extends Identifier<String> {
|
||||
// Public construction is prohibited
|
||||
private VpnPortId(String vpnPortId) {
|
||||
super(vpnPortId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a VPN port identifier.
|
||||
*
|
||||
* @param vpnPortId VPN port identifier
|
||||
* @return VPN port identifier
|
||||
*/
|
||||
public static VpnPortId vpnPortId(String vpnPortId) {
|
||||
return new VpnPortId(vpnPortId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns VPN port identifier.
|
||||
*
|
||||
* @return the VPN port identifier
|
||||
*/
|
||||
public String vpnPortId() {
|
||||
return identifier;
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc.baseport;
|
||||
|
||||
import org.onosproject.event.AbstractEvent;
|
||||
import org.onosproject.evpnopenflow.rsc.BasePort;
|
||||
|
||||
/**
|
||||
* Describes base port event.
|
||||
*/
|
||||
public class BasePortEvent extends AbstractEvent<BasePortEvent.Type,
|
||||
BasePort> {
|
||||
/**
|
||||
* Type of base port events.
|
||||
*/
|
||||
public enum Type {
|
||||
/**
|
||||
* Signifies that base port has been created.
|
||||
*/
|
||||
BASE_PORT_PUT,
|
||||
/**
|
||||
* Signifies that base port has been deleted.
|
||||
*/
|
||||
BASE_PORT_DELETE,
|
||||
/**
|
||||
* Signifies that base port has been updated.
|
||||
*/
|
||||
BASE_PORT_UPDATE
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an event of a given type and for the specified base port.
|
||||
*
|
||||
* @param type base port event type
|
||||
* @param basePort base port subject
|
||||
*/
|
||||
public BasePortEvent(Type type, BasePort basePort) {
|
||||
super(type, basePort);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an event of a given type and for the specified base port.
|
||||
*
|
||||
* @param type base port event type
|
||||
* @param basePort base port subject
|
||||
* @param time occurrence time
|
||||
*/
|
||||
public BasePortEvent(Type type, BasePort basePort, long time) {
|
||||
super(type, basePort, time);
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc.baseport;
|
||||
|
||||
import org.onosproject.event.EventListener;
|
||||
|
||||
/**
|
||||
* Entity capable of base port related events.
|
||||
*/
|
||||
public interface BasePortListener extends EventListener<BasePortEvent> {
|
||||
|
||||
}
|
@ -1,155 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc.baseport;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.onlab.packet.IpAddress;
|
||||
import org.onlab.packet.MacAddress;
|
||||
import org.onosproject.evpnopenflow.rsc.BasePort;
|
||||
import org.onosproject.evpnopenflow.rsc.BasePortId;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.vtnrsc.FixedIp;
|
||||
import org.onosproject.vtnrsc.TenantId;
|
||||
import org.onosproject.vtnrsc.TenantNetworkId;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
|
||||
/**
|
||||
* Service for interacting with the inventory of basePort.
|
||||
*/
|
||||
public interface BasePortService {
|
||||
/**
|
||||
* Returns if the basePort is existed.
|
||||
*
|
||||
* @param basePortId basePort identifier
|
||||
* @return true or false if one with the given identifier is not existed.
|
||||
*/
|
||||
boolean exists(BasePortId basePortId);
|
||||
|
||||
/**
|
||||
* Returns the basePort with the identifier.
|
||||
*
|
||||
* @param basePortId basePort ID
|
||||
* @return BasePort or null if one with the given ID is not know.
|
||||
*/
|
||||
BasePort getPort(BasePortId basePortId);
|
||||
|
||||
/**
|
||||
* Returns the basePort associated with the fixedIP.
|
||||
*
|
||||
* @param fixedIP the fixedIP identifier
|
||||
* @return basePort.
|
||||
*/
|
||||
BasePort getPort(FixedIp fixedIP);
|
||||
|
||||
/**
|
||||
* Returns the basePort associated with the mac address.
|
||||
*
|
||||
* @param mac the mac address
|
||||
* @return basePort.
|
||||
*/
|
||||
BasePort getPort(MacAddress mac);
|
||||
|
||||
/**
|
||||
* Returns the basePort associated with the networkId and ip.
|
||||
*
|
||||
* @param networkId the TenantNetworkId identifier
|
||||
* @param ip the ip identifier
|
||||
* @return basePort.
|
||||
*/
|
||||
BasePort getPort(TenantNetworkId networkId, IpAddress ip);
|
||||
|
||||
/**
|
||||
* Returns the collection of the currently known basePort.
|
||||
*
|
||||
* @return collection of BasePort.
|
||||
*/
|
||||
Collection<BasePort> getPorts();
|
||||
|
||||
/**
|
||||
* Returns the collection of the basePorts associated with the networkId.
|
||||
*
|
||||
* @param networkId the network identifer
|
||||
* @return collection of basePort.
|
||||
*/
|
||||
Collection<BasePort> getPorts(TenantNetworkId networkId);
|
||||
|
||||
/**
|
||||
* Returns the collection of the basePorts associated with the tenantId.
|
||||
*
|
||||
* @param tenantId the tenant identifier
|
||||
* @return collection of basePorts.
|
||||
*/
|
||||
Collection<BasePort> getPorts(TenantId tenantId);
|
||||
|
||||
/**
|
||||
* Returns the collection of the basePorts associated with the deviceId.
|
||||
*
|
||||
* @param deviceId the device identifier
|
||||
* @return collection of basePort.
|
||||
*/
|
||||
Collection<BasePort> getPorts(DeviceId deviceId);
|
||||
|
||||
/**
|
||||
* Creates basePorts by basePorts.
|
||||
*
|
||||
* @param basePorts the iterable collection of basePorts
|
||||
* @return true if all given identifiers created successfully.
|
||||
*/
|
||||
boolean createPorts(Iterable<BasePort> basePorts);
|
||||
|
||||
/**
|
||||
* Updates basePorts by basePorts.
|
||||
*
|
||||
* @param basePorts the iterable collection of basePorts
|
||||
* @return true if all given identifiers updated successfully.
|
||||
*/
|
||||
boolean updatePorts(Iterable<BasePort> basePorts);
|
||||
|
||||
/**
|
||||
* Deletes basePortIds by basePortIds.
|
||||
*
|
||||
* @param basePortIds the iterable collection of basePort identifiers
|
||||
* @return true or false if one with the given identifier to delete is
|
||||
* successfully.
|
||||
*/
|
||||
boolean removePorts(Iterable<BasePortId> basePortIds);
|
||||
|
||||
/**
|
||||
* process gluon config for vpn port information.
|
||||
*
|
||||
* @param action can be either update or delete
|
||||
* @param key can contain the id and also target information
|
||||
* @param value content of the vpn port configuration
|
||||
*/
|
||||
void processGluonConfig(String action, String key, JsonNode value);
|
||||
|
||||
/**
|
||||
* Adds the specified listener to Vpn Port manager.
|
||||
*
|
||||
* @param listener Vpn Port listener
|
||||
*/
|
||||
void addListener(BasePortListener listener);
|
||||
|
||||
/**
|
||||
* Removes the specified listener to Vpn Port manager.
|
||||
*
|
||||
* @param listener Vpn Port listener
|
||||
*/
|
||||
void removeListener(BasePortListener listener);
|
||||
}
|
@ -1,437 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc.baseport.impl;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.onlab.packet.IpAddress;
|
||||
import org.onlab.packet.MacAddress;
|
||||
import org.onlab.util.KryoNamespace;
|
||||
import org.onosproject.core.ApplicationId;
|
||||
import org.onosproject.core.CoreService;
|
||||
import org.onosproject.evpnopenflow.rsc.BasePort;
|
||||
import org.onosproject.evpnopenflow.rsc.BasePortId;
|
||||
import org.onosproject.evpnopenflow.rsc.DefaultBasePort;
|
||||
import org.onosproject.evpnopenflow.rsc.baseport.BasePortEvent;
|
||||
import org.onosproject.evpnopenflow.rsc.baseport.BasePortListener;
|
||||
import org.onosproject.evpnopenflow.rsc.baseport.BasePortService;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.net.Host;
|
||||
import org.onosproject.store.serializers.KryoNamespaces;
|
||||
import org.onosproject.store.service.EventuallyConsistentMap;
|
||||
import org.onosproject.store.service.MultiValuedTimestamp;
|
||||
import org.onosproject.store.service.StorageService;
|
||||
import org.onosproject.store.service.WallClockTimestamp;
|
||||
import org.onosproject.vtnrsc.AllowedAddressPair;
|
||||
import org.onosproject.vtnrsc.BindingHostId;
|
||||
import org.onosproject.vtnrsc.DefaultFloatingIp;
|
||||
import org.onosproject.vtnrsc.FixedIp;
|
||||
import org.onosproject.vtnrsc.FloatingIp;
|
||||
import org.onosproject.vtnrsc.FloatingIpId;
|
||||
import org.onosproject.vtnrsc.RouterId;
|
||||
import org.onosproject.vtnrsc.SecurityGroup;
|
||||
import org.onosproject.vtnrsc.SubnetId;
|
||||
import org.onosproject.vtnrsc.TenantId;
|
||||
import org.onosproject.vtnrsc.TenantNetwork;
|
||||
import org.onosproject.vtnrsc.TenantNetworkId;
|
||||
import org.onosproject.vtnrsc.TenantRouter;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Deactivate;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.APP_ID;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.BASE_PORT_STORE;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.LISTENER_NOT_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.RESPONSE_NOT_NULL;
|
||||
|
||||
/**
|
||||
* Provides implementation of the BasePort APIs.
|
||||
*/
|
||||
@Component(immediate = true, service = BasePortService.class)
|
||||
public class BasePortManager implements BasePortService {
|
||||
|
||||
private final Set<BasePortListener> listeners = Sets
|
||||
.newCopyOnWriteArraySet();
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private static final String BASEPORT_ID_NULL = "BasePort ID cannot be " +
|
||||
"null";
|
||||
private static final String BASEPORT_NOT_NULL = "BasePort cannot be " +
|
||||
"null";
|
||||
private static final String TENANTID_NOT_NULL = "TenantId cannot be null";
|
||||
private static final String NETWORKID_NOT_NULL = "NetworkId cannot be null";
|
||||
private static final String DEVICEID_NOT_NULL = "DeviceId cannot be null";
|
||||
private static final String FIXEDIP_NOT_NULL = "FixedIp cannot be null";
|
||||
private static final String MAC_NOT_NULL = "Mac address cannot be null";
|
||||
private static final String IP_NOT_NULL = "Ip cannot be null";
|
||||
private static final String EVENT_NOT_NULL = "event cannot be null";
|
||||
private static final String SET = "set";
|
||||
private static final String UPDATE = "update";
|
||||
private static final String DELETE = "delete";
|
||||
private static final String SLASH = "/";
|
||||
private static final String PROTON_BASE_PORT = "Port";
|
||||
private static final String JSON_NOT_NULL = "JsonNode can not be null";
|
||||
|
||||
protected EventuallyConsistentMap<BasePortId, BasePort> vPortStore;
|
||||
protected ApplicationId appId;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected StorageService storageService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected CoreService coreService;
|
||||
|
||||
@Activate
|
||||
public void activate() {
|
||||
|
||||
appId = coreService.registerApplication(APP_ID);
|
||||
|
||||
KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
|
||||
.register(KryoNamespaces.API)
|
||||
.register(MultiValuedTimestamp.class)
|
||||
.register(TenantNetworkId.class)
|
||||
.register(Host.class)
|
||||
.register(TenantNetwork.class)
|
||||
.register(TenantNetworkId.class)
|
||||
.register(TenantId.class)
|
||||
.register(SubnetId.class)
|
||||
.register(BasePortId.class)
|
||||
.register(BasePort.State.class)
|
||||
.register(AllowedAddressPair.class)
|
||||
.register(FixedIp.class)
|
||||
.register(FloatingIp.class)
|
||||
.register(FloatingIpId.class)
|
||||
.register(FloatingIp.Status.class)
|
||||
.register(UUID.class)
|
||||
.register(DefaultFloatingIp.class)
|
||||
.register(BindingHostId.class)
|
||||
.register(SecurityGroup.class)
|
||||
.register(IpAddress.class)
|
||||
.register(DefaultBasePort.class)
|
||||
.register(RouterId.class)
|
||||
.register(TenantRouter.class)
|
||||
.register(BasePort.class);
|
||||
vPortStore = storageService
|
||||
.<BasePortId, BasePort>eventuallyConsistentMapBuilder()
|
||||
.withName(BASE_PORT_STORE).withSerializer(serializer)
|
||||
.withTimestampProvider((k, v) -> new WallClockTimestamp())
|
||||
.build();
|
||||
log.info("Started");
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
public void deactivate() {
|
||||
vPortStore.destroy();
|
||||
log.info("Stoppped");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(BasePortId vPortId) {
|
||||
checkNotNull(vPortId, BASEPORT_ID_NULL);
|
||||
return vPortStore.containsKey(vPortId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasePort getPort(BasePortId vPortId) {
|
||||
checkNotNull(vPortId, BASEPORT_ID_NULL);
|
||||
return vPortStore.get(vPortId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasePort getPort(FixedIp fixedIP) {
|
||||
checkNotNull(fixedIP, FIXEDIP_NOT_NULL);
|
||||
List<BasePort> vPorts = new ArrayList<>();
|
||||
vPortStore.values().forEach(p -> {
|
||||
for (FixedIp fixedIp : p.fixedIps()) {
|
||||
if (fixedIp.equals(fixedIP)) {
|
||||
vPorts.add(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (vPorts.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
return vPorts.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasePort getPort(MacAddress mac) {
|
||||
checkNotNull(mac, MAC_NOT_NULL);
|
||||
List<BasePort> vPorts = new ArrayList<>();
|
||||
vPortStore.values().forEach(p -> {
|
||||
if (p.macAddress().equals(mac)) {
|
||||
vPorts.add(p);
|
||||
}
|
||||
});
|
||||
if (vPorts.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
return vPorts.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasePort getPort(TenantNetworkId networkId, IpAddress ip) {
|
||||
checkNotNull(networkId, NETWORKID_NOT_NULL);
|
||||
checkNotNull(ip, IP_NOT_NULL);
|
||||
List<BasePort> vPorts = new ArrayList<>();
|
||||
vPortStore.values().stream().filter(p -> p.networkId().equals(networkId))
|
||||
.forEach(p -> {
|
||||
for (FixedIp fixedIp : p.fixedIps()) {
|
||||
if (fixedIp.ip().equals(ip)) {
|
||||
vPorts.add(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (vPorts.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
return vPorts.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<BasePort> getPorts() {
|
||||
return Collections.unmodifiableCollection(vPortStore.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<BasePort> getPorts(TenantNetworkId networkId) {
|
||||
checkNotNull(networkId, NETWORKID_NOT_NULL);
|
||||
return vPortStore.values().stream().filter(d -> d.networkId().equals(networkId))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<BasePort> getPorts(TenantId tenantId) {
|
||||
checkNotNull(tenantId, TENANTID_NOT_NULL);
|
||||
return vPortStore.values().stream().filter(d -> d.tenantId().equals(tenantId))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<BasePort> getPorts(DeviceId deviceId) {
|
||||
checkNotNull(deviceId, DEVICEID_NOT_NULL);
|
||||
return vPortStore.values().stream().filter(d -> d.deviceId().equals(deviceId))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createPorts(Iterable<BasePort> vPorts) {
|
||||
checkNotNull(vPorts, BASEPORT_NOT_NULL);
|
||||
for (BasePort vPort : vPorts) {
|
||||
log.info("vPortId is {} ", vPort.portId().toString());
|
||||
vPortStore.put(vPort.portId(), vPort);
|
||||
if (!vPortStore.containsKey(vPort.portId())) {
|
||||
log.info("The basePort is created failed whose identifier is" +
|
||||
" {} ",
|
||||
vPort.portId().toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updatePorts(Iterable<BasePort> vPorts) {
|
||||
checkNotNull(vPorts, BASEPORT_NOT_NULL);
|
||||
for (BasePort vPort : vPorts) {
|
||||
vPortStore.put(vPort.portId(), vPort);
|
||||
if (!vPortStore.containsKey(vPort.portId())) {
|
||||
log.info("The basePort is not exist whose identifier is {}",
|
||||
vPort.portId().toString());
|
||||
return false;
|
||||
}
|
||||
|
||||
vPortStore.put(vPort.portId(), vPort);
|
||||
|
||||
if (!vPort.equals(vPortStore.get(vPort.portId()))) {
|
||||
log.info("The basePort is updated failed whose identifier " +
|
||||
"is {}",
|
||||
vPort.portId().toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removePorts(Iterable<BasePortId> vPortIds) {
|
||||
checkNotNull(vPortIds, BASEPORT_ID_NULL);
|
||||
for (BasePortId vPortId : vPortIds) {
|
||||
vPortStore.remove(vPortId);
|
||||
if (vPortStore.containsKey(vPortId)) {
|
||||
log.info("The basePort is removed failed whose identifier is" +
|
||||
" {}",
|
||||
vPortId.toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of basePorts from subnetNodes.
|
||||
*
|
||||
* @param vPortNodes the basePort json node
|
||||
* @return BasePort collection of vpn ports
|
||||
*/
|
||||
private Collection<BasePort> changeJsonToSub(JsonNode vPortNodes) {
|
||||
checkNotNull(vPortNodes, JSON_NOT_NULL);
|
||||
Set<FixedIp> fixedIps = null;
|
||||
TenantNetworkId tenantNetworkId = null;
|
||||
Map<BasePortId, BasePort> vportMap = new HashMap<>();
|
||||
Map<String, String> strMap = new HashMap<>();
|
||||
BasePortId basePortId = BasePortId.portId(vPortNodes.get("id").asText());
|
||||
String name = vPortNodes.get("name").asText();
|
||||
TenantId tenantId = TenantId
|
||||
.tenantId(vPortNodes.get("tenant_id").asText());
|
||||
Boolean adminStateUp = vPortNodes.get("admin_state_up").asBoolean();
|
||||
String state = vPortNodes.get("status").asText();
|
||||
MacAddress macAddress = MacAddress
|
||||
.valueOf(vPortNodes.get("mac_address").asText());
|
||||
DeviceId deviceId = DeviceId
|
||||
.deviceId(vPortNodes.get("device_id").asText());
|
||||
String deviceOwner = vPortNodes.get("device_owner").asText();
|
||||
BindingHostId bindingHostId = BindingHostId
|
||||
.bindingHostId(vPortNodes.get("host_id").asText());
|
||||
String bindingVnicType = vPortNodes.get("vnic_type").asText();
|
||||
String bindingVifType = vPortNodes.get("vif_type").asText();
|
||||
String bindingVifDetails = vPortNodes.get("vif_details").asText();
|
||||
strMap.put("name", name);
|
||||
strMap.put("deviceOwner", deviceOwner);
|
||||
strMap.put("bindingVnicType", bindingVnicType);
|
||||
strMap.put("bindingVifType", bindingVifType);
|
||||
strMap.put("bindingVifDetails", bindingVifDetails);
|
||||
BasePort prevBasePort = getPort(basePortId);
|
||||
if (prevBasePort != null) {
|
||||
fixedIps = prevBasePort.fixedIps();
|
||||
tenantNetworkId = prevBasePort.networkId();
|
||||
}
|
||||
BasePort vPort = new DefaultBasePort(basePortId,
|
||||
tenantNetworkId,
|
||||
adminStateUp,
|
||||
strMap, state,
|
||||
macAddress, tenantId,
|
||||
deviceId, fixedIps,
|
||||
bindingHostId,
|
||||
null,
|
||||
null);
|
||||
vportMap.put(basePortId, vPort);
|
||||
|
||||
return Collections.unmodifiableCollection(vportMap.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns BasePort State.
|
||||
*
|
||||
* @param state the base port state
|
||||
* @return the basePort state
|
||||
*/
|
||||
private BasePort.State isState(String state) {
|
||||
if (state.equals("ACTIVE")) {
|
||||
return BasePort.State.ACTIVE;
|
||||
} else {
|
||||
return BasePort.State.DOWN;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* process Etcd response for port information.
|
||||
*
|
||||
* @param action can be either update or delete
|
||||
* @param key can contain the id and also target information
|
||||
* @param value content of the port configuration
|
||||
*/
|
||||
@Override
|
||||
public void processGluonConfig(String action, String key, JsonNode value) {
|
||||
Collection<BasePort> basePorts;
|
||||
switch (action) {
|
||||
case DELETE:
|
||||
String[] list = key.split(SLASH);
|
||||
BasePortId basePortId
|
||||
= BasePortId.portId(list[list.length - 1]);
|
||||
Set<BasePortId> basePortIds = Sets.newHashSet(basePortId);
|
||||
removePorts(basePortIds);
|
||||
break;
|
||||
case SET:
|
||||
checkNotNull(value, RESPONSE_NOT_NULL);
|
||||
basePorts = changeJsonToSub(value);
|
||||
createPorts(basePorts);
|
||||
break;
|
||||
case UPDATE:
|
||||
checkNotNull(value, RESPONSE_NOT_NULL);
|
||||
basePorts = changeJsonToSub(value);
|
||||
updatePorts(basePorts);
|
||||
break;
|
||||
default:
|
||||
log.info("Invalid action is received while processing VPN " +
|
||||
"port configuration");
|
||||
}
|
||||
}
|
||||
|
||||
private void parseEtcdResponse(JsonNode jsonNode,
|
||||
String key,
|
||||
String action) {
|
||||
JsonNode modifyValue = null;
|
||||
if (action.equals(SET)) {
|
||||
modifyValue = jsonNode.get(key);
|
||||
}
|
||||
String[] list = key.split(SLASH);
|
||||
String target = list[list.length - 2];
|
||||
if (target.equals(PROTON_BASE_PORT)) {
|
||||
processGluonConfig(action, key, modifyValue);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(BasePortListener listener) {
|
||||
checkNotNull(listener, LISTENER_NOT_NULL);
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener(BasePortListener listener) {
|
||||
checkNotNull(listener, LISTENER_NOT_NULL);
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies specify event to all listeners.
|
||||
*
|
||||
* @param event vpn af config event
|
||||
*/
|
||||
private void notifyListeners(BasePortEvent event) {
|
||||
checkNotNull(event, EVENT_NOT_NULL);
|
||||
listeners.forEach(listener -> listener.event(event));
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* VPN resources that used by l3vpn.
|
||||
*/
|
||||
package org.onosproject.evpnopenflow.rsc.baseport.impl;
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* VPN resources that used by l3vpn.
|
||||
*/
|
||||
package org.onosproject.evpnopenflow.rsc.baseport;
|
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc.cli;
|
||||
|
||||
import org.apache.karaf.shell.api.action.Command;
|
||||
import org.apache.karaf.shell.api.action.lifecycle.Service;
|
||||
import org.onosproject.cli.AbstractShellCommand;
|
||||
import org.onosproject.evpnopenflow.manager.EvpnService;
|
||||
import org.onosproject.evpnopenflow.manager.impl.EvpnManager;
|
||||
import org.onosproject.evpnrouteservice.EvpnInstanceRoute;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.FORMAT_PRIVATE_ROUTE;
|
||||
|
||||
/**
|
||||
* Support for displaying EVPN private routes.
|
||||
*/
|
||||
@Service
|
||||
@Command(scope = "onos", name = "evpn-private-routes", description = "Lists" +
|
||||
" all EVPN private routes")
|
||||
public class EvpnPrivateRouteListCommand extends AbstractShellCommand {
|
||||
private static final String FORMAT_HEADER =
|
||||
" VPN name Prefix Next Hop";
|
||||
|
||||
@Override
|
||||
protected void doExecute() {
|
||||
EvpnService service = AbstractShellCommand.get(EvpnService.class);
|
||||
EvpnManager evpnManager = (EvpnManager) service;
|
||||
Collection<EvpnInstanceRoute> evpnRoutes = evpnManager.evpnInstanceRoutes;
|
||||
if (evpnRoutes != null) {
|
||||
print(FORMAT_HEADER);
|
||||
evpnRoutes.forEach(evpnInstanceRoute -> {
|
||||
print(FORMAT_PRIVATE_ROUTE, evpnInstanceRoute.evpnInstanceName(),
|
||||
evpnInstanceRoute.prefix().address().getIp4Address(), evpnInstanceRoute
|
||||
.getNextHopl());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc.cli;
|
||||
|
||||
import org.apache.karaf.shell.api.action.Command;
|
||||
import org.apache.karaf.shell.api.action.lifecycle.Service;
|
||||
import org.onosproject.cli.AbstractShellCommand;
|
||||
import org.onosproject.evpnrouteservice.EvpnRoute;
|
||||
import org.onosproject.evpnrouteservice.EvpnRouteSet;
|
||||
import org.onosproject.evpnrouteservice.EvpnRouteStore;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.FORMAT_PUBLIC_ROUTE;
|
||||
|
||||
/**
|
||||
* Support for displaying EVPN public routes.
|
||||
*/
|
||||
@Service
|
||||
@Command(scope = "onos", name = "evpn-public-routes", description = "Lists" +
|
||||
" all EVPN public routes")
|
||||
public class EvpnPublicRouteListCommand extends AbstractShellCommand {
|
||||
private static final String FORMAT_HEADER =
|
||||
" MAC Prefix Next Hop";
|
||||
|
||||
@Override
|
||||
protected void doExecute() {
|
||||
EvpnRouteStore evpnRouteStore = AbstractShellCommand.get(EvpnRouteStore.class);
|
||||
|
||||
evpnRouteStore.getRouteTables().forEach(routeTableId -> {
|
||||
Collection<EvpnRouteSet> routes
|
||||
= evpnRouteStore.getRoutes(routeTableId);
|
||||
if (routes != null) {
|
||||
routes.forEach(route -> {
|
||||
Collection<EvpnRoute> evpnRoutes = route.routes();
|
||||
print(FORMAT_HEADER);
|
||||
evpnRoutes.forEach(evpnRoute -> {
|
||||
print(FORMAT_PUBLIC_ROUTE, evpnRoute.prefixMac(),
|
||||
evpnRoute.prefixIp().address().getIp4Address(),
|
||||
evpnRoute.ipNextHop());
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc.cli;
|
||||
|
||||
import org.apache.karaf.shell.api.action.Command;
|
||||
import org.apache.karaf.shell.api.action.lifecycle.Service;
|
||||
import org.onosproject.cli.AbstractShellCommand;
|
||||
import org.onosproject.evpnopenflow.rsc.EvpnConstants;
|
||||
import org.onosproject.evpnopenflow.rsc.VpnInstance;
|
||||
import org.onosproject.evpnopenflow.rsc.vpninstance.VpnInstanceService;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Support for displaying EVPN VPN instances.
|
||||
*/
|
||||
@Service
|
||||
@Command(scope = "onos", name = "evpn-instance-list", description = "Lists " +
|
||||
"all EVPN instances")
|
||||
public class VpnInstListCommand extends AbstractShellCommand {
|
||||
|
||||
@Override
|
||||
protected void doExecute() {
|
||||
VpnInstanceService service = get(VpnInstanceService.class);
|
||||
Collection<VpnInstance> vpnInstances = service
|
||||
.getInstances();
|
||||
vpnInstances.forEach(vpnInstance -> {
|
||||
print(EvpnConstants.FORMAT_VPN_INSTANCE, vpnInstance.id(),
|
||||
vpnInstance.description(),
|
||||
vpnInstance.vpnInstanceName(),
|
||||
vpnInstance.routeDistinguisher(),
|
||||
vpnInstance.getExportRouteTargets(),
|
||||
vpnInstance.getImportRouteTargets());
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc.cli;
|
||||
|
||||
import org.apache.karaf.shell.api.action.Command;
|
||||
import org.apache.karaf.shell.api.action.lifecycle.Service;
|
||||
import org.onosproject.cli.AbstractShellCommand;
|
||||
import org.onosproject.evpnopenflow.rsc.VpnPort;
|
||||
import org.onosproject.evpnopenflow.rsc.vpnport.VpnPortService;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.FORMAT_VPN_PORT;
|
||||
|
||||
/**
|
||||
* Support for displaying EVPN VPN ports.
|
||||
*/
|
||||
@Service
|
||||
@Command(scope = "onos", name = "evpn-port-list", description = "Lists all" +
|
||||
"EVPN ports")
|
||||
public class VpnPortListCommand extends AbstractShellCommand {
|
||||
|
||||
@Override
|
||||
protected void doExecute() {
|
||||
VpnPortService portService = get(VpnPortService.class);
|
||||
Collection<VpnPort> ports = portService.getPorts();
|
||||
ports.forEach(port -> {
|
||||
print(FORMAT_VPN_PORT, port.id(), port.vpnInstanceId());
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implementation CLI for EVPN services.
|
||||
*/
|
||||
package org.onosproject.evpnopenflow.rsc.cli;
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* EVPN resource package.
|
||||
*/
|
||||
package org.onosproject.evpnopenflow.rsc;
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc.vpnafconfig;
|
||||
|
||||
import org.onosproject.event.AbstractEvent;
|
||||
import org.onosproject.evpnopenflow.rsc.VpnAfConfig;
|
||||
|
||||
/**
|
||||
* Describes network VPN af config event.
|
||||
*/
|
||||
public class VpnAfConfigEvent extends AbstractEvent<VpnAfConfigEvent.Type, VpnAfConfig> {
|
||||
|
||||
/**
|
||||
* Type of VPN port events.
|
||||
*/
|
||||
public enum Type {
|
||||
/**
|
||||
* Signifies that VPN af config has been set.
|
||||
*/
|
||||
VPN_AF_CONFIG_SET,
|
||||
/**
|
||||
* Signifies that VPN af config has been deleted.
|
||||
*/
|
||||
VPN_AF_CONFIG_DELETE,
|
||||
/**
|
||||
* Signifies that VPN af config has been updated.
|
||||
*/
|
||||
VPN_AF_CONFIG_UPDATE
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an event of a given type and for the specified VPN af config.
|
||||
*
|
||||
* @param type VPN af config type
|
||||
* @param vpnAfConfig VPN af config subject
|
||||
*/
|
||||
public VpnAfConfigEvent(Type type, VpnAfConfig vpnAfConfig) {
|
||||
super(type, vpnAfConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an event of a given type and for the specified VPN af config.
|
||||
*
|
||||
* @param type VPN af config type
|
||||
* @param vpnAfConfig VPN af config subject
|
||||
* @param time occurrence time
|
||||
*/
|
||||
public VpnAfConfigEvent(Type type, VpnAfConfig vpnAfConfig, long time) {
|
||||
super(type, vpnAfConfig, time);
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc.vpnafconfig;
|
||||
|
||||
import org.onosproject.event.EventListener;
|
||||
|
||||
/**
|
||||
* Entity capable of VPN af config related events.
|
||||
*/
|
||||
public interface VpnAfConfigListener extends EventListener<VpnAfConfigEvent> {
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc.vpnafconfig;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.onosproject.evpnopenflow.rsc.VpnAfConfig;
|
||||
import org.onosproject.evpnrouteservice.VpnRouteTarget;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Service for interacting with the inventory of VPN af config instance.
|
||||
*/
|
||||
public interface VpnAfConfigService {
|
||||
/**
|
||||
* Returns if the route target is existed.
|
||||
*
|
||||
* @param routeTarget route target
|
||||
* @return true or false if one with the given route target is not existed.
|
||||
*/
|
||||
boolean exists(VpnRouteTarget routeTarget);
|
||||
|
||||
/**
|
||||
* Returns the VPN af config with the route target.
|
||||
*
|
||||
* @param routeTarget route target
|
||||
* @return VPN af config or null if one with the given route target is not
|
||||
* know.
|
||||
*/
|
||||
VpnAfConfig getVpnAfConfig(VpnRouteTarget routeTarget);
|
||||
|
||||
/**
|
||||
* Returns the collection of the currently known VPN af configurations.
|
||||
*
|
||||
* @return collection of VPN af configurations.
|
||||
*/
|
||||
Collection<VpnAfConfig> getVpnAfConfigs();
|
||||
|
||||
/**
|
||||
* Creates VPN af configurations by vpnAfConfigs.
|
||||
*
|
||||
* @param vpnAfConfigs the iterable collection of vpnAfConfigs
|
||||
* @return true if all given VPN af configs created successfully
|
||||
*/
|
||||
boolean createVpnAfConfigs(Iterable<VpnAfConfig> vpnAfConfigs);
|
||||
|
||||
/**
|
||||
* Updates VPN af configurations by vpnAfConfigs.
|
||||
*
|
||||
* @param vpnAfConfigs the iterable collection of vpnAfConfigs
|
||||
* @return true if all given VPN af configs created successfully.
|
||||
*/
|
||||
boolean updateVpnAfConfigs(Iterable<VpnAfConfig> vpnAfConfigs);
|
||||
|
||||
/**
|
||||
* Deletes vpnAfConfigs by route target.
|
||||
*
|
||||
* @param routeTarget the iterable collection of vpnAFConfigs
|
||||
* @return true or false if one with the given route target to delete is
|
||||
* successfully
|
||||
*/
|
||||
boolean removeVpnAfConfigs(Iterable<VpnRouteTarget> routeTarget);
|
||||
|
||||
/**
|
||||
* process gluon config for vpn af configuration.
|
||||
*
|
||||
* @param action can be either update or delete
|
||||
* @param key can contain the id and also target information
|
||||
* @param value content of the route targets configuration
|
||||
*/
|
||||
void processGluonConfig(String action, String key, JsonNode value);
|
||||
|
||||
/**
|
||||
* Adds the specified listener to Vpn Port manager.
|
||||
*
|
||||
* @param listener vpn af config listener
|
||||
*/
|
||||
void addListener(VpnAfConfigListener listener);
|
||||
|
||||
/**
|
||||
* Removes the specified listener to vpn af config manager.
|
||||
*
|
||||
* @param listener vpn af config listener
|
||||
*/
|
||||
void removeListener(VpnAfConfigListener listener);
|
||||
}
|
@ -1,266 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc.vpnafconfig.impl;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.onlab.util.KryoNamespace;
|
||||
import org.onosproject.core.CoreService;
|
||||
import org.onosproject.evpnopenflow.rsc.DefaultVpnAfConfig;
|
||||
import org.onosproject.evpnopenflow.rsc.VpnAfConfig;
|
||||
import org.onosproject.evpnopenflow.rsc.vpnafconfig.VpnAfConfigEvent;
|
||||
import org.onosproject.evpnopenflow.rsc.vpnafconfig.VpnAfConfigListener;
|
||||
import org.onosproject.evpnopenflow.rsc.vpnafconfig.VpnAfConfigService;
|
||||
import org.onosproject.evpnrouteservice.VpnRouteTarget;
|
||||
import org.onosproject.store.serializers.KryoNamespaces;
|
||||
import org.onosproject.store.service.EventuallyConsistentMap;
|
||||
import org.onosproject.store.service.StorageService;
|
||||
import org.onosproject.store.service.WallClockTimestamp;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Deactivate;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.APP_ID;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.DELETE;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EVENT_NOT_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EVPN_VPN_AF_CONFIG_START;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EVPN_VPN_AF_CONFIG_STOP;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EXPORT_ROUTE_POLICY;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.IMPORT_ROUTE_POLICY;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.INVALID_ACTION_VPN_AF_CONFIG;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.JSON_NOT_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.LISTENER_NOT_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.RESPONSE_NOT_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ROUTE_TARGET_CANNOT_NOT_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ROUTE_TARGET_DELETE_FAILED;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ROUTE_TARGET_VALUE;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.SET;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.SLASH;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.UPDATE;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_AF_CONFIG_CREATION_FAILED;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_AF_CONFIG_IS_NOT_EXIST;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_AF_CONFIG_NOT_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_AF_CONFIG_STORE;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_AF_CONFIG_UPDATE_FAILED;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_ID_NOT_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VRF_RT_TYPE;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VRF_RT_VALUE;
|
||||
|
||||
/**
|
||||
* Provides implementation of the VPN af config APIs.
|
||||
*/
|
||||
@Component(immediate = true, service = VpnAfConfigService.class)
|
||||
public class VpnAfConfigManager implements VpnAfConfigService {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private final Set<VpnAfConfigListener> listeners = Sets
|
||||
.newCopyOnWriteArraySet();
|
||||
|
||||
protected EventuallyConsistentMap<VpnRouteTarget, VpnAfConfig>
|
||||
vpnAfConfigStore;
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected StorageService storageService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected CoreService coreService;
|
||||
|
||||
@Activate
|
||||
public void activate() {
|
||||
coreService.registerApplication(APP_ID);
|
||||
KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
|
||||
.register(KryoNamespaces.API).register(VpnAfConfig.class)
|
||||
.register(VpnRouteTarget.class);
|
||||
vpnAfConfigStore = storageService
|
||||
.<VpnRouteTarget, VpnAfConfig>eventuallyConsistentMapBuilder()
|
||||
.withName(VPN_AF_CONFIG_STORE).withSerializer(serializer)
|
||||
.withTimestampProvider((k, v) -> new WallClockTimestamp())
|
||||
.build();
|
||||
log.info(EVPN_VPN_AF_CONFIG_START);
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
public void deactivate() {
|
||||
vpnAfConfigStore.destroy();
|
||||
log.info(EVPN_VPN_AF_CONFIG_STOP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(VpnRouteTarget routeTarget) {
|
||||
checkNotNull(routeTarget, ROUTE_TARGET_CANNOT_NOT_NULL);
|
||||
return vpnAfConfigStore.containsKey(routeTarget);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VpnAfConfig getVpnAfConfig(VpnRouteTarget routeTarget) {
|
||||
checkNotNull(routeTarget, ROUTE_TARGET_CANNOT_NOT_NULL);
|
||||
return vpnAfConfigStore.get(routeTarget);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<VpnAfConfig> getVpnAfConfigs() {
|
||||
return Collections.unmodifiableCollection(vpnAfConfigStore.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createVpnAfConfigs(Iterable<VpnAfConfig> vpnAfConfigs) {
|
||||
checkNotNull(vpnAfConfigs, VPN_AF_CONFIG_NOT_NULL);
|
||||
for (VpnAfConfig vpnAfConfig : vpnAfConfigs) {
|
||||
log.info(ROUTE_TARGET_VALUE, vpnAfConfig
|
||||
.routeTarget().getRouteTarget());
|
||||
vpnAfConfigStore.put(vpnAfConfig.routeTarget(), vpnAfConfig);
|
||||
if (!vpnAfConfigStore.containsKey(vpnAfConfig.routeTarget())) {
|
||||
log.info(VPN_AF_CONFIG_CREATION_FAILED,
|
||||
vpnAfConfig.routeTarget().getRouteTarget());
|
||||
return false;
|
||||
}
|
||||
notifyListeners(new VpnAfConfigEvent(VpnAfConfigEvent
|
||||
.Type
|
||||
.VPN_AF_CONFIG_SET,
|
||||
vpnAfConfig));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateVpnAfConfigs(Iterable<VpnAfConfig> vpnAfConfigs) {
|
||||
checkNotNull(vpnAfConfigs, VPN_AF_CONFIG_NOT_NULL);
|
||||
for (VpnAfConfig vpnAfConfig : vpnAfConfigs) {
|
||||
if (!vpnAfConfigStore.containsKey(vpnAfConfig.routeTarget())) {
|
||||
log.info(VPN_AF_CONFIG_IS_NOT_EXIST,
|
||||
vpnAfConfig.routeTarget().getRouteTarget());
|
||||
return false;
|
||||
}
|
||||
vpnAfConfigStore.put(vpnAfConfig.routeTarget(), vpnAfConfig);
|
||||
if (!vpnAfConfig.equals(vpnAfConfigStore
|
||||
.get(vpnAfConfig.routeTarget()))) {
|
||||
log.info(VPN_AF_CONFIG_UPDATE_FAILED,
|
||||
vpnAfConfig.routeTarget().getRouteTarget());
|
||||
return false;
|
||||
}
|
||||
notifyListeners(new VpnAfConfigEvent(VpnAfConfigEvent
|
||||
.Type
|
||||
.VPN_AF_CONFIG_UPDATE,
|
||||
vpnAfConfig));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeVpnAfConfigs(Iterable<VpnRouteTarget> routeTargets) {
|
||||
checkNotNull(routeTargets, VPN_INSTANCE_ID_NOT_NULL);
|
||||
for (VpnRouteTarget routeTarget : routeTargets) {
|
||||
VpnAfConfig vpnAfConfig = vpnAfConfigStore.get(routeTarget);
|
||||
vpnAfConfigStore.remove(routeTarget);
|
||||
if (vpnAfConfigStore.containsKey(routeTarget)) {
|
||||
log.info(ROUTE_TARGET_DELETE_FAILED,
|
||||
routeTarget.getRouteTarget());
|
||||
return false;
|
||||
}
|
||||
notifyListeners(new VpnAfConfigEvent(VpnAfConfigEvent
|
||||
.Type
|
||||
.VPN_AF_CONFIG_DELETE,
|
||||
vpnAfConfig));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processGluonConfig(String action, String key, JsonNode value) {
|
||||
Collection<VpnAfConfig> vpnAfConfigs;
|
||||
switch (action) {
|
||||
case DELETE:
|
||||
String[] list = key.split(SLASH);
|
||||
VpnRouteTarget routeTarget = VpnRouteTarget
|
||||
.routeTarget(list[list.length - 1]);
|
||||
Set<VpnRouteTarget> routeTargets
|
||||
= Sets.newHashSet(routeTarget);
|
||||
removeVpnAfConfigs(routeTargets);
|
||||
break;
|
||||
case SET:
|
||||
checkNotNull(value, RESPONSE_NOT_NULL);
|
||||
vpnAfConfigs = changeJsonToSub(value);
|
||||
createVpnAfConfigs(vpnAfConfigs);
|
||||
break;
|
||||
case UPDATE:
|
||||
checkNotNull(value, RESPONSE_NOT_NULL);
|
||||
vpnAfConfigs = changeJsonToSub(value);
|
||||
updateVpnAfConfigs(vpnAfConfigs);
|
||||
break;
|
||||
default:
|
||||
log.info(INVALID_ACTION_VPN_AF_CONFIG);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of vpn af configuration.
|
||||
*
|
||||
* @param vpnAfConfigNode the vpn af configuration json node
|
||||
* @return returns the collection of vpn af configuration
|
||||
*/
|
||||
private Collection<VpnAfConfig> changeJsonToSub(JsonNode vpnAfConfigNode) {
|
||||
checkNotNull(vpnAfConfigNode, JSON_NOT_NULL);
|
||||
Map<VpnRouteTarget, VpnAfConfig> vpnAfConfigMap = new HashMap<>();
|
||||
String exportRoutePolicy
|
||||
= vpnAfConfigNode.get(EXPORT_ROUTE_POLICY).asText();
|
||||
String importRoutePolicy
|
||||
= vpnAfConfigNode.get(IMPORT_ROUTE_POLICY).asText();
|
||||
String routeTargetType = vpnAfConfigNode.get(VRF_RT_TYPE).asText();
|
||||
VpnRouteTarget routeTarget = VpnRouteTarget
|
||||
.routeTarget(vpnAfConfigNode.get(VRF_RT_VALUE).asText());
|
||||
|
||||
VpnAfConfig vpnAfConfig = new DefaultVpnAfConfig(exportRoutePolicy,
|
||||
importRoutePolicy,
|
||||
routeTarget,
|
||||
routeTargetType);
|
||||
vpnAfConfigMap.put(routeTarget, vpnAfConfig);
|
||||
|
||||
return Collections.unmodifiableCollection(vpnAfConfigMap.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(VpnAfConfigListener listener) {
|
||||
checkNotNull(listener, LISTENER_NOT_NULL);
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener(VpnAfConfigListener listener) {
|
||||
checkNotNull(listener, LISTENER_NOT_NULL);
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies specify event to all listeners.
|
||||
*
|
||||
* @param event vpn af config event
|
||||
*/
|
||||
private void notifyListeners(VpnAfConfigEvent event) {
|
||||
checkNotNull(event, EVENT_NOT_NULL);
|
||||
listeners.forEach(listener -> listener.event(event));
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* VPN af configuration that used by l3vpn.
|
||||
*/
|
||||
package org.onosproject.evpnopenflow.rsc.vpnafconfig.impl;
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* VPN resources that used by Evpn.
|
||||
*/
|
||||
package org.onosproject.evpnopenflow.rsc.vpnafconfig;
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc.vpninstance;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.onosproject.evpnopenflow.rsc.VpnInstance;
|
||||
import org.onosproject.evpnopenflow.rsc.VpnInstanceId;
|
||||
import org.onosproject.evpnrouteservice.VpnRouteTarget;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Service for interacting with the inventory of VPN instance.
|
||||
*/
|
||||
public interface VpnInstanceService {
|
||||
/**
|
||||
* Returns if the vpnInstance is existed.
|
||||
*
|
||||
* @param vpnInstanceId vpnInstance identifier
|
||||
* @return true or false if one with the given identifier is not existed.
|
||||
*/
|
||||
boolean exists(VpnInstanceId vpnInstanceId);
|
||||
|
||||
/**
|
||||
* Returns the vpnInstance with the identifier.
|
||||
*
|
||||
* @param vpnInstanceId vpnInstance ID
|
||||
* @return VpnInstance or null if one with the given ID is not know.
|
||||
*/
|
||||
VpnInstance getInstance(VpnInstanceId vpnInstanceId);
|
||||
|
||||
/**
|
||||
* Returns the collection of the currently known vpnInstance.
|
||||
*
|
||||
* @return collection of VpnInstance.
|
||||
*/
|
||||
Collection<VpnInstance> getInstances();
|
||||
|
||||
/**
|
||||
* Creates vpnInstances by vpnInstances.
|
||||
*
|
||||
* @param vpnInstances the iterable collection of vpnInstances
|
||||
* @return true if all given identifiers created successfully.
|
||||
*/
|
||||
boolean createInstances(Iterable<VpnInstance> vpnInstances);
|
||||
|
||||
/**
|
||||
* Updates vpnInstances by vpnInstances.
|
||||
*
|
||||
* @param vpnInstances the iterable collection of vpnInstances
|
||||
* @return true if all given identifiers updated successfully.
|
||||
*/
|
||||
boolean updateInstances(Iterable<VpnInstance> vpnInstances);
|
||||
|
||||
/**
|
||||
* Deletes vpnInstanceIds by vpnInstanceIds.
|
||||
*
|
||||
* @param vpnInstanceIds the iterable collection of vpnInstance identifiers
|
||||
* @return true or false if one with the given identifier to delete is
|
||||
* successfully.
|
||||
*/
|
||||
boolean removeInstances(Iterable<VpnInstanceId> vpnInstanceIds);
|
||||
|
||||
/**
|
||||
* process gluon config for vpn instance information.
|
||||
*
|
||||
* @param action can be either update or delete
|
||||
* @param key can contain the id and also target information
|
||||
* @param value content of the vpn instance configuration
|
||||
*/
|
||||
void processGluonConfig(String action, String key, JsonNode value);
|
||||
|
||||
/**
|
||||
* process Etcd response for vpn instance information.
|
||||
*
|
||||
* @param routeTargetType route target type
|
||||
* @param exportRouteTargets export route targets
|
||||
* @param importRouteTargets import route targets
|
||||
* @param vpnRouteTarget vpn route target
|
||||
*/
|
||||
void updateImpExpRouteTargets(String routeTargetType,
|
||||
Set<VpnRouteTarget> exportRouteTargets,
|
||||
Set<VpnRouteTarget> importRouteTargets,
|
||||
VpnRouteTarget vpnRouteTarget);
|
||||
}
|
@ -1,288 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc.vpninstance.impl;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.onlab.util.KryoNamespace;
|
||||
import org.onosproject.core.ApplicationId;
|
||||
import org.onosproject.core.CoreService;
|
||||
import org.onosproject.evpnopenflow.rsc.DefaultVpnInstance;
|
||||
import org.onosproject.evpnopenflow.rsc.VpnAfConfig;
|
||||
import org.onosproject.evpnopenflow.rsc.VpnInstance;
|
||||
import org.onosproject.evpnopenflow.rsc.VpnInstanceId;
|
||||
import org.onosproject.evpnopenflow.rsc.vpnafconfig.VpnAfConfigService;
|
||||
import org.onosproject.evpnopenflow.rsc.vpninstance.VpnInstanceService;
|
||||
import org.onosproject.evpnrouteservice.EvpnInstanceName;
|
||||
import org.onosproject.evpnrouteservice.RouteDistinguisher;
|
||||
import org.onosproject.evpnrouteservice.VpnRouteTarget;
|
||||
import org.onosproject.routeservice.RouteAdminService;
|
||||
import org.onosproject.store.serializers.KryoNamespaces;
|
||||
import org.onosproject.store.service.EventuallyConsistentMap;
|
||||
import org.onosproject.store.service.StorageService;
|
||||
import org.onosproject.store.service.WallClockTimestamp;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Deactivate;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.APP_ID;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.COMMA;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.DELETE;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.DESCRIPTION;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EVPN_VPN_INSTANCE_START;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EVPN_VPN_INSTANCE_STOP;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ID;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.INSTANCE_ID;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.IPV4_FAMILY;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.JSON_NOT_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.RESPONSE_NOT_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.ROUTE_DISTINGUISHERS;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.SET;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.SLASH;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.UPDATE;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_CREATION_FAILED;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_DELETE_FAILED;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_ID_NOT_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_IS_NOT_EXIST;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_NAME;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_NOT_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_STORE;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE_UPDATE_FAILED;
|
||||
|
||||
|
||||
/**
|
||||
* Provides implementation of the VpnInstance APIs.
|
||||
*/
|
||||
@Component(immediate = true, service = VpnInstanceService.class)
|
||||
public class VpnInstanceManager implements VpnInstanceService {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
protected EventuallyConsistentMap<VpnInstanceId, VpnInstance> vpnInstanceStore;
|
||||
protected ApplicationId appId;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected StorageService storageService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected RouteAdminService routeService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected CoreService coreService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected VpnAfConfigService vpnAfConfigService;
|
||||
|
||||
@Activate
|
||||
public void activate() {
|
||||
appId = coreService.registerApplication(APP_ID);
|
||||
KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
|
||||
.register(KryoNamespaces.API).register(VpnInstance.class)
|
||||
.register(VpnInstanceId.class);
|
||||
vpnInstanceStore = storageService
|
||||
.<VpnInstanceId, VpnInstance>eventuallyConsistentMapBuilder()
|
||||
.withName(VPN_INSTANCE_STORE).withSerializer(serializer)
|
||||
.withTimestampProvider((k, v) -> new WallClockTimestamp())
|
||||
.build();
|
||||
log.info(EVPN_VPN_INSTANCE_START);
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
public void deactivate() {
|
||||
vpnInstanceStore.destroy();
|
||||
log.info(EVPN_VPN_INSTANCE_STOP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(VpnInstanceId vpnInstanceId) {
|
||||
checkNotNull(vpnInstanceId, VPN_INSTANCE_ID_NOT_NULL);
|
||||
return vpnInstanceStore.containsKey(vpnInstanceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VpnInstance getInstance(VpnInstanceId vpnInstanceId) {
|
||||
checkNotNull(vpnInstanceId, VPN_INSTANCE_ID_NOT_NULL);
|
||||
return vpnInstanceStore.get(vpnInstanceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<VpnInstance> getInstances() {
|
||||
return Collections.unmodifiableCollection(vpnInstanceStore.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createInstances(Iterable<VpnInstance> vpnInstances) {
|
||||
checkNotNull(vpnInstances, VPN_INSTANCE_NOT_NULL);
|
||||
for (VpnInstance vpnInstance : vpnInstances) {
|
||||
log.info(INSTANCE_ID, vpnInstance.id().toString());
|
||||
vpnInstanceStore.put(vpnInstance.id(), vpnInstance);
|
||||
if (!vpnInstanceStore.containsKey(vpnInstance.id())) {
|
||||
log.info(VPN_INSTANCE_CREATION_FAILED,
|
||||
vpnInstance.id().toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateInstances(Iterable<VpnInstance> vpnInstances) {
|
||||
checkNotNull(vpnInstances, VPN_INSTANCE_NOT_NULL);
|
||||
for (VpnInstance vpnInstance : vpnInstances) {
|
||||
if (!vpnInstanceStore.containsKey(vpnInstance.id())) {
|
||||
log.info(VPN_INSTANCE_IS_NOT_EXIST,
|
||||
vpnInstance.id().toString());
|
||||
return false;
|
||||
}
|
||||
vpnInstanceStore.put(vpnInstance.id(), vpnInstance);
|
||||
if (!vpnInstance.equals(vpnInstanceStore.get(vpnInstance.id()))) {
|
||||
log.info(VPN_INSTANCE_UPDATE_FAILED,
|
||||
vpnInstance.id().toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeInstances(Iterable<VpnInstanceId> vpnInstanceIds) {
|
||||
checkNotNull(vpnInstanceIds, VPN_INSTANCE_ID_NOT_NULL);
|
||||
for (VpnInstanceId vpnInstanceId : vpnInstanceIds) {
|
||||
vpnInstanceStore.remove(vpnInstanceId);
|
||||
if (vpnInstanceStore.containsKey(vpnInstanceId)) {
|
||||
log.info(VPN_INSTANCE_DELETE_FAILED, vpnInstanceId.toString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processGluonConfig(String action, String key, JsonNode value) {
|
||||
Collection<VpnInstance> vpnInstances;
|
||||
switch (action) {
|
||||
case DELETE:
|
||||
String[] list = key.split(SLASH);
|
||||
VpnInstanceId vpnInstanceId = VpnInstanceId
|
||||
.vpnInstanceId(list[list.length - 1]);
|
||||
Set<VpnInstanceId> vpnInstanceIds
|
||||
= Sets.newHashSet(vpnInstanceId);
|
||||
removeInstances(vpnInstanceIds);
|
||||
break;
|
||||
case SET:
|
||||
checkNotNull(value, RESPONSE_NOT_NULL);
|
||||
vpnInstances = changeJsonToSub(value);
|
||||
createInstances(vpnInstances);
|
||||
break;
|
||||
case UPDATE:
|
||||
checkNotNull(value, RESPONSE_NOT_NULL);
|
||||
vpnInstances = changeJsonToSub(value);
|
||||
updateInstances(vpnInstances);
|
||||
break;
|
||||
default:
|
||||
log.info("Invalid action is received while processing VPN " +
|
||||
"instance configuration");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateImpExpRouteTargets(String routeTargetType,
|
||||
Set<VpnRouteTarget> exportRouteTargets,
|
||||
Set<VpnRouteTarget> importRouteTargets,
|
||||
VpnRouteTarget vpnRouteTarget) {
|
||||
switch (routeTargetType) {
|
||||
case "export_extcommunity":
|
||||
exportRouteTargets.add(vpnRouteTarget);
|
||||
break;
|
||||
case "import_extcommunity":
|
||||
importRouteTargets.add(vpnRouteTarget);
|
||||
break;
|
||||
case "both":
|
||||
exportRouteTargets.add(vpnRouteTarget);
|
||||
importRouteTargets.add(vpnRouteTarget);
|
||||
break;
|
||||
default:
|
||||
log.info("Invalid route target type has received");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of vpnInstances from subnetNodes.
|
||||
*
|
||||
* @param vpnInstanceNodes the vpnInstance json node
|
||||
* @return returns the collection of vpn instances
|
||||
*/
|
||||
private Collection<VpnInstance> changeJsonToSub(JsonNode vpnInstanceNodes) {
|
||||
checkNotNull(vpnInstanceNodes, JSON_NOT_NULL);
|
||||
|
||||
Set<VpnRouteTarget> exportRouteTargets = new HashSet<>();
|
||||
Set<VpnRouteTarget> importRouteTargets = new HashSet<>();
|
||||
Set<VpnRouteTarget> configRouteTargets = new HashSet<>();
|
||||
|
||||
Map<VpnInstanceId, VpnInstance> vpnInstanceMap = new HashMap<>();
|
||||
VpnInstanceId id = VpnInstanceId
|
||||
.vpnInstanceId(vpnInstanceNodes.get(ID).asText());
|
||||
EvpnInstanceName name = EvpnInstanceName
|
||||
.evpnName(vpnInstanceNodes.get(VPN_INSTANCE_NAME).asText());
|
||||
String description = vpnInstanceNodes.get(DESCRIPTION).asText();
|
||||
RouteDistinguisher routeDistinguisher = RouteDistinguisher
|
||||
.routeDistinguisher(vpnInstanceNodes.get(ROUTE_DISTINGUISHERS)
|
||||
.asText());
|
||||
String routeTargets = vpnInstanceNodes.get(IPV4_FAMILY).asText();
|
||||
String[] list = routeTargets.split(COMMA);
|
||||
|
||||
for (String routeTarget : list) {
|
||||
// Converting route target string into route target object and
|
||||
// then storing into configuration route target set.
|
||||
VpnRouteTarget vpnRouteTarget
|
||||
= VpnRouteTarget.routeTarget(routeTarget);
|
||||
configRouteTargets.add(vpnRouteTarget);
|
||||
VpnAfConfig vpnAfConfig
|
||||
= vpnAfConfigService.getVpnAfConfig(vpnRouteTarget);
|
||||
if (vpnAfConfig == null) {
|
||||
log.info("Not able to find vpn af config for the give vpn " +
|
||||
"route target");
|
||||
break;
|
||||
}
|
||||
updateImpExpRouteTargets(vpnAfConfig.routeTargetType(),
|
||||
exportRouteTargets,
|
||||
importRouteTargets,
|
||||
vpnRouteTarget);
|
||||
}
|
||||
|
||||
VpnInstance vpnInstance = new DefaultVpnInstance(id, name, description,
|
||||
routeDistinguisher,
|
||||
exportRouteTargets,
|
||||
importRouteTargets,
|
||||
configRouteTargets);
|
||||
vpnInstanceMap.put(id, vpnInstance);
|
||||
return Collections.unmodifiableCollection(vpnInstanceMap.values());
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* VPN resources that used by l3vpn.
|
||||
*/
|
||||
package org.onosproject.evpnopenflow.rsc.vpninstance.impl;
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* EVPN VPN instance implementation.
|
||||
*/
|
||||
package org.onosproject.evpnopenflow.rsc.vpninstance;
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc.vpnport;
|
||||
|
||||
import org.onosproject.event.AbstractEvent;
|
||||
import org.onosproject.evpnopenflow.rsc.VpnPort;
|
||||
|
||||
/**
|
||||
* Describes network VPN port event.
|
||||
*/
|
||||
public class VpnPortEvent extends AbstractEvent<VpnPortEvent.Type, VpnPort> {
|
||||
|
||||
/**
|
||||
* Type of VPN port events.
|
||||
*/
|
||||
public enum Type {
|
||||
/**
|
||||
* Signifies that VPN port has been set.
|
||||
*/
|
||||
VPN_PORT_SET,
|
||||
/**
|
||||
* Signifies that VPN port has been deleted.
|
||||
*/
|
||||
VPN_PORT_DELETE,
|
||||
/**
|
||||
* Signifies that VPN port has been updated.
|
||||
*/
|
||||
VPN_PORT_UPDATE
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an event of a given type and for the specified VPN port.
|
||||
*
|
||||
* @param type VPN port type
|
||||
* @param vpnPort VPN port subject
|
||||
*/
|
||||
public VpnPortEvent(Type type, VpnPort vpnPort) {
|
||||
super(type, vpnPort);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an event of a given type and for the specified VPN port.
|
||||
*
|
||||
* @param type VPN port type
|
||||
* @param vpnPort VPN port subject
|
||||
* @param time occurrence time
|
||||
*/
|
||||
public VpnPortEvent(Type type, VpnPort vpnPort, long time) {
|
||||
super(type, vpnPort, time);
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc.vpnport;
|
||||
|
||||
import org.onosproject.event.EventListener;
|
||||
|
||||
/**
|
||||
* Entity capable of VPN port related events.
|
||||
*/
|
||||
public interface VpnPortListener extends EventListener<VpnPortEvent> {
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc.vpnport;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.onosproject.evpnopenflow.rsc.VpnPort;
|
||||
import org.onosproject.evpnopenflow.rsc.VpnPortId;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
|
||||
/**
|
||||
* Service for interacting with the inventory of VPN port.
|
||||
*/
|
||||
public interface VpnPortService {
|
||||
/**
|
||||
* Returns if the vpnPort is existed.
|
||||
*
|
||||
* @param vpnPortId vpnPort identifier
|
||||
* @return true or false if one with the given identifier is not existed.
|
||||
*/
|
||||
boolean exists(VpnPortId vpnPortId);
|
||||
|
||||
/**
|
||||
* Returns the vpnPort with the identifier.
|
||||
*
|
||||
* @param vpnPortId vpnPort ID
|
||||
* @return VpnPort or null if one with the given ID is not know.
|
||||
*/
|
||||
VpnPort getPort(VpnPortId vpnPortId);
|
||||
|
||||
/**
|
||||
* Returns the collection of the currently known vpnPort.
|
||||
*
|
||||
* @return collection of VpnPort.
|
||||
*/
|
||||
Collection<VpnPort> getPorts();
|
||||
|
||||
/**
|
||||
* Creates vpnPorts by vpnPorts.
|
||||
*
|
||||
* @param vpnPorts the iterable collection of vpnPorts
|
||||
* @return true if all given identifiers created successfully.
|
||||
*/
|
||||
boolean createPorts(Iterable<VpnPort> vpnPorts);
|
||||
|
||||
/**
|
||||
* Updates vpnPorts by vpnPorts.
|
||||
*
|
||||
* @param vpnPorts the iterable collection of vpnPorts
|
||||
* @return true if all given identifiers updated successfully.
|
||||
*/
|
||||
boolean updatePorts(Iterable<VpnPort> vpnPorts);
|
||||
|
||||
/**
|
||||
* Deletes vpnPortIds by vpnPortIds.
|
||||
*
|
||||
* @param vpnPortIds the iterable collection of vpnPort identifiers
|
||||
* @return true or false if one with the given identifier to delete is
|
||||
* successfully.
|
||||
*/
|
||||
boolean removePorts(Iterable<VpnPortId> vpnPortIds);
|
||||
|
||||
/**
|
||||
* process gluon config for vpn port information.
|
||||
*
|
||||
* @param action can be either update or delete
|
||||
* @param key can contain the id and also target information
|
||||
* @param value content of the vpn port configuration
|
||||
*/
|
||||
void processGluonConfig(String action, String key, JsonNode value);
|
||||
|
||||
/**
|
||||
* Adds the specified listener to Vpn Port manager.
|
||||
*
|
||||
* @param listener Vpn Port listener
|
||||
*/
|
||||
void addListener(VpnPortListener listener);
|
||||
|
||||
/**
|
||||
* Removes the specified listener to Vpn Port manager.
|
||||
*
|
||||
* @param listener Vpn Port listener
|
||||
*/
|
||||
void removeListener(VpnPortListener listener);
|
||||
}
|
@ -1,427 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.evpnopenflow.rsc.vpnport.impl;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.onlab.packet.IpAddress;
|
||||
import org.onlab.packet.IpPrefix;
|
||||
import org.onlab.packet.MacAddress;
|
||||
import org.onlab.util.KryoNamespace;
|
||||
import org.onosproject.core.ApplicationId;
|
||||
import org.onosproject.core.CoreService;
|
||||
import org.onosproject.evpnopenflow.rsc.BasePort;
|
||||
import org.onosproject.evpnopenflow.rsc.BasePortId;
|
||||
import org.onosproject.evpnopenflow.rsc.DefaultVpnPort;
|
||||
import org.onosproject.evpnopenflow.rsc.VpnInstanceId;
|
||||
import org.onosproject.evpnopenflow.rsc.VpnPort;
|
||||
import org.onosproject.evpnopenflow.rsc.VpnPortId;
|
||||
import org.onosproject.evpnopenflow.rsc.baseport.BasePortService;
|
||||
import org.onosproject.evpnopenflow.rsc.vpnport.VpnPortEvent;
|
||||
import org.onosproject.evpnopenflow.rsc.vpnport.VpnPortListener;
|
||||
import org.onosproject.evpnopenflow.rsc.vpnport.VpnPortService;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.store.serializers.KryoNamespaces;
|
||||
import org.onosproject.store.service.EventuallyConsistentMap;
|
||||
import org.onosproject.store.service.StorageService;
|
||||
import org.onosproject.store.service.WallClockTimestamp;
|
||||
import org.onosproject.vtnrsc.AllocationPool;
|
||||
import org.onosproject.vtnrsc.BindingHostId;
|
||||
import org.onosproject.vtnrsc.DefaultSubnet;
|
||||
import org.onosproject.vtnrsc.DefaultTenantNetwork;
|
||||
import org.onosproject.vtnrsc.DefaultVirtualPort;
|
||||
import org.onosproject.vtnrsc.FixedIp;
|
||||
import org.onosproject.vtnrsc.HostRoute;
|
||||
import org.onosproject.vtnrsc.PhysicalNetwork;
|
||||
import org.onosproject.vtnrsc.SegmentationId;
|
||||
import org.onosproject.vtnrsc.Subnet;
|
||||
import org.onosproject.vtnrsc.SubnetId;
|
||||
import org.onosproject.vtnrsc.TenantId;
|
||||
import org.onosproject.vtnrsc.TenantNetwork;
|
||||
import org.onosproject.vtnrsc.TenantNetworkId;
|
||||
import org.onosproject.vtnrsc.VirtualPort;
|
||||
import org.onosproject.vtnrsc.VirtualPortId;
|
||||
import org.onosproject.vtnrsc.subnet.SubnetService;
|
||||
import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
|
||||
import org.onosproject.vtnrsc.virtualport.VirtualPortService;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Deactivate;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.APP_ID;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.DELETE;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EVENT_NOT_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EVPN_VPN_PORT_START;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.EVPN_VPN_PORT_STOP;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.INTERFACE_ID;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.JSON_NOT_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.LISTENER_NOT_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.RESPONSE_NOT_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.SET;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.SLASH;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.UPDATE;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_INSTANCE;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_CREATION_FAILED;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_DELETE_FAILED;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_ID;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_ID_NOT_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_IS_NOT_EXIST;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_NOT_NULL;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_STORE;
|
||||
import static org.onosproject.evpnopenflow.rsc.EvpnConstants.VPN_PORT_UPDATE_FAILED;
|
||||
|
||||
/**
|
||||
* Provides implementation of the VpnPort service.
|
||||
*/
|
||||
@Component(immediate = true, service = VpnPortService.class)
|
||||
public class VpnPortManager implements VpnPortService {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private final Set<VpnPortListener> listeners = Sets
|
||||
.newCopyOnWriteArraySet();
|
||||
|
||||
protected EventuallyConsistentMap<VpnPortId, VpnPort> vpnPortStore;
|
||||
protected ApplicationId appId;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected StorageService storageService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected CoreService coreService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected BasePortService basePortService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected VirtualPortService virtualPortService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected TenantNetworkService tenantNetworkService;
|
||||
|
||||
@Reference(cardinality = ReferenceCardinality.MANDATORY)
|
||||
protected SubnetService subnetService;
|
||||
|
||||
@Activate
|
||||
|
||||
public void activate() {
|
||||
appId = coreService.registerApplication(APP_ID);
|
||||
KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
|
||||
.register(KryoNamespaces.API).register(VpnPort.class)
|
||||
.register(VpnPortId.class);
|
||||
vpnPortStore = storageService
|
||||
.<VpnPortId, VpnPort>eventuallyConsistentMapBuilder()
|
||||
.withName(VPN_PORT_STORE).withSerializer(serializer)
|
||||
.withTimestampProvider((k, v) -> new WallClockTimestamp())
|
||||
.build();
|
||||
log.info(EVPN_VPN_PORT_START);
|
||||
}
|
||||
|
||||
@Deactivate
|
||||
public void deactivate() {
|
||||
vpnPortStore.destroy();
|
||||
log.info(EVPN_VPN_PORT_STOP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(VpnPortId vpnPortId) {
|
||||
checkNotNull(vpnPortId, VPN_PORT_ID_NOT_NULL);
|
||||
return vpnPortStore.containsKey(vpnPortId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VpnPort getPort(VpnPortId vpnPortId) {
|
||||
checkNotNull(vpnPortId, VPN_PORT_ID_NOT_NULL);
|
||||
return vpnPortStore.get(vpnPortId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<VpnPort> getPorts() {
|
||||
return Collections.unmodifiableCollection(vpnPortStore.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createPorts(Iterable<VpnPort> vpnPorts) {
|
||||
checkNotNull(vpnPorts, VPN_PORT_NOT_NULL);
|
||||
for (VpnPort vpnPort : vpnPorts) {
|
||||
log.info(VPN_PORT_ID, vpnPort.id().toString());
|
||||
vpnPortStore.put(vpnPort.id(), vpnPort);
|
||||
if (!vpnPortStore.containsKey(vpnPort.id())) {
|
||||
log.info(VPN_PORT_CREATION_FAILED, vpnPort.id().toString());
|
||||
return false;
|
||||
}
|
||||
notifyListeners(new VpnPortEvent(VpnPortEvent.Type.VPN_PORT_SET,
|
||||
vpnPort));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updatePorts(Iterable<VpnPort> vpnPorts) {
|
||||
checkNotNull(vpnPorts, VPN_PORT_NOT_NULL);
|
||||
for (VpnPort vpnPort : vpnPorts) {
|
||||
if (!vpnPortStore.containsKey(vpnPort.id())) {
|
||||
log.info(VPN_PORT_IS_NOT_EXIST, vpnPort.id().toString());
|
||||
return false;
|
||||
}
|
||||
vpnPortStore.put(vpnPort.id(), vpnPort);
|
||||
if (!vpnPort.equals(vpnPortStore.get(vpnPort.id()))) {
|
||||
log.info(VPN_PORT_UPDATE_FAILED, vpnPort.id().toString());
|
||||
return false;
|
||||
}
|
||||
notifyListeners(new VpnPortEvent(VpnPortEvent.Type.VPN_PORT_UPDATE,
|
||||
vpnPort));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removePorts(Iterable<VpnPortId> vpnPortIds) {
|
||||
checkNotNull(vpnPortIds, VPN_PORT_NOT_NULL);
|
||||
for (VpnPortId vpnPortid : vpnPortIds) {
|
||||
VpnPort vpnPort = vpnPortStore.get(vpnPortid);
|
||||
vpnPortStore.remove(vpnPortid);
|
||||
if (vpnPortStore.containsKey(vpnPortid)) {
|
||||
log.info(VPN_PORT_DELETE_FAILED, vpnPortid.toString());
|
||||
return false;
|
||||
}
|
||||
notifyListeners(new VpnPortEvent(VpnPortEvent.Type.VPN_PORT_DELETE,
|
||||
vpnPort));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processGluonConfig(String action, String key, JsonNode value) {
|
||||
Collection<VpnPort> vpnPorts;
|
||||
switch (action) {
|
||||
case DELETE:
|
||||
String[] list = key.split(SLASH);
|
||||
VpnPortId vpnPortId
|
||||
= VpnPortId.vpnPortId(list[list.length - 1]);
|
||||
Set<VpnPortId> vpnPortIds = Sets.newHashSet(vpnPortId);
|
||||
removePorts(vpnPortIds);
|
||||
// After removing vpn port and also remove virtual port from vtn
|
||||
VirtualPortId virtualPortId
|
||||
= VirtualPortId.portId(list[list.length - 1]);
|
||||
Set<VirtualPortId> virtualPortIds
|
||||
= Sets.newHashSet(virtualPortId);
|
||||
virtualPortService.removePorts(virtualPortIds);
|
||||
break;
|
||||
case SET:
|
||||
checkNotNull(value, RESPONSE_NOT_NULL);
|
||||
vpnPorts = changeJsonToSub(value);
|
||||
createPorts(vpnPorts);
|
||||
break;
|
||||
case UPDATE:
|
||||
checkNotNull(value, RESPONSE_NOT_NULL);
|
||||
vpnPorts = changeJsonToSub(value);
|
||||
updatePorts(vpnPorts);
|
||||
break;
|
||||
default:
|
||||
log.info("Invalid action is received while processing VPN " +
|
||||
"port configuration");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates dummy gluon network to the VTN.
|
||||
*
|
||||
* @param state the base port state
|
||||
* @param adminStateUp the base port admin status
|
||||
* @param tenantID the base port tenant ID
|
||||
*/
|
||||
private void createDummyGluonNetwork(boolean adminStateUp, String state,
|
||||
TenantId tenantID) {
|
||||
String id = "11111111-1111-1111-1111-111111111111";
|
||||
String name = "GluonNetwork";
|
||||
String segmentationID = "50";
|
||||
String physicalNetwork = "None";
|
||||
|
||||
TenantNetwork network = new DefaultTenantNetwork(TenantNetworkId.networkId(id), name,
|
||||
adminStateUp,
|
||||
TenantNetwork.State.valueOf(state),
|
||||
false, tenantID,
|
||||
false,
|
||||
TenantNetwork.Type.LOCAL,
|
||||
PhysicalNetwork.physicalNetwork(physicalNetwork),
|
||||
SegmentationId.segmentationId(segmentationID));
|
||||
|
||||
Set<TenantNetwork> networksSet = Sets.newHashSet(network);
|
||||
tenantNetworkService.createNetworks(networksSet);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates dummy gluon subnet to the VTN.
|
||||
*
|
||||
* @param tenantId the base port tenant ID
|
||||
*/
|
||||
public void createDummySubnet(TenantId tenantId) {
|
||||
String id = "22222222-2222-2222-2222-222222222222";
|
||||
String subnetName = "GluonSubnet";
|
||||
String cidr = "0.0.0.0/0";
|
||||
String gatewayIp = "0.0.0.0";
|
||||
Set<HostRoute> hostRoutes = Sets.newHashSet();
|
||||
TenantNetworkId tenantNetworkId = null;
|
||||
Set<AllocationPool> allocationPools = Sets.newHashSet();
|
||||
Iterable<TenantNetwork> networks
|
||||
= tenantNetworkService.getNetworks();
|
||||
|
||||
for (TenantNetwork tenantNetwork : networks) {
|
||||
if (tenantNetwork.name().equals("GluonNetwork")) {
|
||||
tenantNetworkId = tenantNetwork.id();
|
||||
break;
|
||||
}
|
||||
}
|
||||
Subnet subnet = new DefaultSubnet(SubnetId.subnetId(id), subnetName,
|
||||
tenantNetworkId,
|
||||
tenantId, IpAddress.Version.INET,
|
||||
IpPrefix.valueOf(cidr),
|
||||
IpAddress.valueOf(gatewayIp),
|
||||
false, false, hostRoutes,
|
||||
null,
|
||||
null,
|
||||
allocationPools);
|
||||
|
||||
Set<Subnet> subnetsSet = Sets.newHashSet(subnet);
|
||||
subnetService.createSubnets(subnetsSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of vpnPort from subnetNodes.
|
||||
*
|
||||
* @param vpnPortNodes the vpnPort json node
|
||||
* @return list of vpnports
|
||||
*/
|
||||
private Collection<VpnPort> changeJsonToSub(JsonNode vpnPortNodes) {
|
||||
checkNotNull(vpnPortNodes, JSON_NOT_NULL);
|
||||
Map<VpnPortId, VpnPort> vpnPortMap = new HashMap<>();
|
||||
String interfaceId = vpnPortNodes.get(INTERFACE_ID).asText();
|
||||
VpnPortId vpnPortId = VpnPortId.vpnPortId(interfaceId);
|
||||
VpnInstanceId vpnInstanceId = VpnInstanceId
|
||||
.vpnInstanceId(vpnPortNodes.get(VPN_INSTANCE).asText());
|
||||
VpnPort vpnPort = new DefaultVpnPort(vpnPortId, vpnInstanceId);
|
||||
vpnPortMap.put(vpnPortId, vpnPort);
|
||||
// update ip address and tenant network information in vtn
|
||||
TenantNetworkId tenantNetworkId = null;
|
||||
Map<VirtualPortId, VirtualPort> vPortMap = new HashMap<>();
|
||||
BasePortId basePortId = BasePortId.portId(interfaceId);
|
||||
VirtualPortId virtualPortId = VirtualPortId.portId(interfaceId);
|
||||
BasePort bPort = basePortService.getPort(basePortId);
|
||||
if (bPort != null) {
|
||||
FixedIp fixedIp = FixedIp.fixedIp(SubnetId.subnetId(basePortId.toString()),
|
||||
IpAddress.valueOf(vpnPortNodes
|
||||
.get("ipaddress").asText()));
|
||||
Set<FixedIp> fixedIps = new HashSet<>();
|
||||
fixedIps.add(fixedIp);
|
||||
Map<String, String> strMap = new HashMap<>();
|
||||
boolean adminStateUp = bPort.adminStateUp();
|
||||
strMap.put("name", bPort.name());
|
||||
strMap.put("deviceOwner", bPort.deviceOwner());
|
||||
strMap.put("bindingVnicType", bPort.bindingVnicType());
|
||||
strMap.put("bindingVifType", bPort.bindingVifType());
|
||||
strMap.put("bindingVifDetails", bPort.bindingVifDetails());
|
||||
String state = bPort.state();
|
||||
MacAddress macAddress = bPort.macAddress();
|
||||
TenantId tenantId = bPort.tenantId();
|
||||
DeviceId deviceId = bPort.deviceId();
|
||||
BindingHostId bindingHostId = bPort.bindingHostId();
|
||||
// Creates Dummy Gluon Network and Subnet
|
||||
createDummyGluonNetwork(adminStateUp, state, tenantId);
|
||||
createDummySubnet(tenantId);
|
||||
|
||||
Iterable<TenantNetwork> networks
|
||||
= tenantNetworkService.getNetworks();
|
||||
|
||||
for (TenantNetwork tenantNetwork : networks) {
|
||||
if (tenantNetwork.name().equals("GluonNetwork")) {
|
||||
tenantNetworkId = tenantNetwork.id();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tenantNetworkId != null) {
|
||||
|
||||
DefaultVirtualPort vPort = new DefaultVirtualPort(virtualPortId,
|
||||
tenantNetworkId,
|
||||
adminStateUp,
|
||||
strMap, isState(state),
|
||||
macAddress, tenantId,
|
||||
deviceId, fixedIps,
|
||||
bindingHostId,
|
||||
null,
|
||||
null);
|
||||
vPortMap.put(virtualPortId, vPort);
|
||||
Collection<VirtualPort> virtualPorts
|
||||
= Collections.unmodifiableCollection(vPortMap.values());
|
||||
virtualPortService.createPorts(virtualPorts);
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.unmodifiableCollection(vpnPortMap.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns BasePort State.
|
||||
*
|
||||
* @param state the base port state
|
||||
* @return the basePort state
|
||||
*/
|
||||
private VirtualPort.State isState(String state) {
|
||||
if (state.equals("ACTIVE")) {
|
||||
return VirtualPort.State.ACTIVE;
|
||||
} else {
|
||||
return VirtualPort.State.DOWN;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(VpnPortListener listener) {
|
||||
checkNotNull(listener, LISTENER_NOT_NULL);
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener(VpnPortListener listener) {
|
||||
checkNotNull(listener, LISTENER_NOT_NULL);
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies specify event to all listeners.
|
||||
*
|
||||
* @param event Vpn Port event
|
||||
*/
|
||||
private void notifyListeners(VpnPortEvent event) {
|
||||
checkNotNull(event, EVENT_NOT_NULL);
|
||||
listeners.forEach(listener -> {
|
||||
listener.event(event);
|
||||
});
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* VPN resources that used by l3vpn.
|
||||
*/
|
||||
package org.onosproject.evpnopenflow.rsc.vpnport.impl;
|
@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* VPN resources that used by evpn.
|
||||
*/
|
||||
package org.onosproject.evpnopenflow.rsc.vpnport;
|
@ -1,43 +0,0 @@
|
||||
COMPILE_DEPS = CORE_DEPS + KRYO + ONOS_YANG + [
|
||||
"//models/l3vpn:onos-models-l3vpn",
|
||||
"//apps/config:onos-apps-config",
|
||||
"//core/store/serializers:onos-core-serializers",
|
||||
"//apps/yang:onos-apps-yang",
|
||||
"//apps/pce/app:onos-apps-pce-app",
|
||||
"//apps/tunnel/api:onos-apps-tunnel-api",
|
||||
"//models/common:onos-models-common",
|
||||
]
|
||||
|
||||
TEST_DEPS = TEST_ADAPTERS + [
|
||||
"//utils/osgi:onlab-osgi-tests",
|
||||
]
|
||||
|
||||
APPS = [
|
||||
"org.onosproject.yang",
|
||||
"org.onosproject.yang-gui",
|
||||
"org.onosproject.config",
|
||||
"org.onosproject.restconf",
|
||||
"org.onosproject.protocols.restconfserver",
|
||||
"org.onosproject.tunnel",
|
||||
"org.onosproject.netconf",
|
||||
"org.onosproject.netconfsb",
|
||||
"org.onosproject.models.common",
|
||||
"org.onosproject.models.l3vpn",
|
||||
"org.onosproject.bgpcep",
|
||||
"org.onosproject.pcep",
|
||||
"org.onosproject.bgp",
|
||||
]
|
||||
|
||||
osgi_jar_with_tests(
|
||||
test_deps = TEST_DEPS,
|
||||
deps = COMPILE_DEPS,
|
||||
)
|
||||
|
||||
onos_app(
|
||||
app_name = "org.onosproject.l3vpn",
|
||||
category = "Traffic Engineering",
|
||||
description = "L3VPN YANG Application",
|
||||
required_apps = APPS,
|
||||
title = "YANG L3VPN",
|
||||
url = "http://onosproject.org",
|
||||
)
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.l3vpn.netl3vpn;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* Representation of site network access information.
|
||||
*/
|
||||
public class AccessInfo {
|
||||
|
||||
/**
|
||||
* Site id from sites list.
|
||||
*/
|
||||
private String siteId;
|
||||
|
||||
/**
|
||||
* Site network access id from site network access list.
|
||||
*/
|
||||
private String accessId;
|
||||
|
||||
/**
|
||||
* Constructs access info with site id and access id.
|
||||
*
|
||||
* @param s site id
|
||||
* @param a access id
|
||||
*/
|
||||
public AccessInfo(String s, String a) {
|
||||
siteId = s;
|
||||
accessId = a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the site id.
|
||||
*
|
||||
* @return site id
|
||||
*/
|
||||
public String siteId() {
|
||||
return siteId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the access id.
|
||||
*
|
||||
* @return access id
|
||||
*/
|
||||
public String accessId() {
|
||||
return accessId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(siteId, accessId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (this == object) {
|
||||
return true;
|
||||
}
|
||||
if (object instanceof AccessInfo) {
|
||||
AccessInfo that = (AccessInfo) object;
|
||||
return Objects.equal(siteId, that.siteId) &&
|
||||
Objects.equal(accessId, that.accessId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Access id : " + accessId + "\nSite id : " + siteId;
|
||||
}
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.l3vpn.netl3vpn;
|
||||
|
||||
/**
|
||||
* Representation of BGP configuration required for driver to process.
|
||||
*/
|
||||
public class BgpDriverInfo {
|
||||
|
||||
/**
|
||||
* Model id level of the BGP information that needed to be added in store.
|
||||
*/
|
||||
private ModelIdLevel modIdLevel;
|
||||
|
||||
/**
|
||||
* Device id required for the creation of driver model object data.
|
||||
*/
|
||||
private String devId;
|
||||
|
||||
/**
|
||||
* Constructs BGP driver info.
|
||||
*
|
||||
* @param m model id level for BGP
|
||||
* @param d device id
|
||||
*/
|
||||
public BgpDriverInfo(ModelIdLevel m, String d) {
|
||||
modIdLevel = m;
|
||||
devId = d;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the model id level of the BGP information to be added.
|
||||
*
|
||||
* @return model id level
|
||||
*/
|
||||
public ModelIdLevel modIdLevel() {
|
||||
return modIdLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the device id.
|
||||
*
|
||||
* @return device id
|
||||
*/
|
||||
public String devId() {
|
||||
return devId;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user