Adding EVPN App code
Change-Id: Id3b2192f56f054cadcd8384092245b8757a781a9
diff --git a/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnafconfig/VpnAfConfigEvent.java b/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnafconfig/VpnAfConfigEvent.java
new file mode 100755
index 0000000..944698c
--- /dev/null
+++ b/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnafconfig/VpnAfConfigEvent.java
@@ -0,0 +1,65 @@
+/*
+ * 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);
+ }
+}
diff --git a/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnafconfig/VpnAfConfigListener.java b/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnafconfig/VpnAfConfigListener.java
new file mode 100755
index 0000000..42db841
--- /dev/null
+++ b/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnafconfig/VpnAfConfigListener.java
@@ -0,0 +1,25 @@
+/*
+ * 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> {
+}
diff --git a/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnafconfig/VpnAfConfigService.java b/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnafconfig/VpnAfConfigService.java
new file mode 100755
index 0000000..31714ad
--- /dev/null
+++ b/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnafconfig/VpnAfConfigService.java
@@ -0,0 +1,100 @@
+/*
+ * 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.incubator.net.routing.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);
+}
diff --git a/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnafconfig/impl/VpnAfConfigManager.java b/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnafconfig/impl/VpnAfConfigManager.java
new file mode 100755
index 0000000..fafd5d8
--- /dev/null
+++ b/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnafconfig/impl/VpnAfConfigManager.java
@@ -0,0 +1,268 @@
+/*
+ * 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.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.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.incubator.net.routing.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.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
+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_UNARY)
+ protected StorageService storageService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ 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));
+ }
+}
diff --git a/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnafconfig/impl/package-info.java b/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnafconfig/impl/package-info.java
new file mode 100755
index 0000000..f2dd128
--- /dev/null
+++ b/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnafconfig/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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;
\ No newline at end of file
diff --git a/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnafconfig/package-info.java b/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnafconfig/package-info.java
new file mode 100755
index 0000000..7c2e4f4
--- /dev/null
+++ b/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnafconfig/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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;