From 3510292a1184e25751f8690ea49a8c2312bba4b3 Mon Sep 17 00:00:00 2001 From: epgoraj Date: Thu, 14 Jan 2016 17:25:23 +0530 Subject: [PATCH] ELAN FT Support for BE Change-Id: Iedbdea5f47c2bbe706acbed80cd89eac6d3c0e6a Signed-off-by: epgoraj --- elanmanager/elanmanager-api/pom.xml | 63 + .../elanmanager/api/IElanService.java | 35 + .../exceptions/MacNotFoundException.java | 22 + .../src/main/yang/elan-statistics.yang | 32 + .../elanmanager-api/src/main/yang/elan.yang | 240 ++++ .../src/main/yang/elanmanager-api.yang | 20 + elanmanager/elanmanager-impl/pom.xml | 60 + .../src/main/config/default-config.xml | 63 + .../vpnservice/elan/cli/ElanAdd.java | 52 + .../vpnservice/elan/cli/ElanDelete.java | 46 + .../vpnservice/elan/cli/ElanGet.java | 74 ++ .../vpnservice/elan/cli/ElanInterfaceAdd.java | 53 + .../elan/cli/ElanInterfaceDelete.java | 48 + .../vpnservice/elan/cli/ElanInterfaceGet.java | 95 ++ .../elan/cli/ElanInterfaceUpdate.java | 54 + .../elan/cli/ElanMacTableFlush.java | 45 + .../vpnservice/elan/cli/ElanMacTableGet.java | 67 + .../vpnservice/elan/cli/ElanUpdate.java | 48 + .../vpnservice/elan/cli/StaticMacAdd.java | 50 + .../vpnservice/elan/cli/StaticMacDelete.java | 44 + .../ElanForwardingEntriesHandler.java | 154 +++ .../elan/internal/ElanInstanceManager.java | 162 +++ .../elan/internal/ElanInterfaceManager.java | 1133 +++++++++++++++++ .../elan/internal/ElanItmEventListener.java | 96 ++ .../elan/internal/ElanNodeListener.java | 112 ++ .../elan/internal/ElanPacketInHandler.java | 155 +++ .../elan/internal/ElanServiceProvider.java | 402 ++++++ .../internal/ElanSmacFlowEventListener.java | 125 ++ .../elan/statisitcs/ElanStatisticsImpl.java | 134 ++ .../vpnservice/elan/utils/ElanCLIUtils.java | 15 + .../vpnservice/elan/utils/ElanConstants.java | 35 + .../vpnservice/elan/utils/ElanUtils.java | 795 ++++++++++++ .../impl/rev150216/ElanServiceImplModule.java | 37 + .../ElanServiceImplModuleFactory.java | 13 + .../OSGI-INF/blueprint/blueprint.xml | 67 + .../src/main/yang/elanservice-impl.yang | 81 ++ elanmanager/pom.xml | 49 + features/pom.xml | 26 + features/src/main/features/features.xml | 6 + .../InterfaceAlreadyExistsException.java | 25 + .../InterfaceNotFoundException.java | 25 + .../InterfaceServiceNotFoundException.java | 23 + .../interfacemgr/globals/IfmConstants.java | 44 + .../interfacemgr/globals/InterfaceInfo.java | 135 ++ .../globals/InterfaceServiceUtil.java | 100 ++ .../globals/LogicalGroupInterfaceInfo.java | 53 + .../globals/VlanInterfaceInfo.java | 47 + .../interfaces/IInterfaceManager.java | 10 +- .../src/main/yang/interface-statistics.yang | 58 + .../vpnservice/interfacemgr/IfmConstants.java | 12 +- .../vpnservice/interfacemgr/IfmUtil.java | 78 +- .../interfacemgr/InterfacemgrProvider.java | 121 +- .../vpnservice/itm/globals/ITMConstants.java | 7 +- mdsalutil/mdsalutil-api/pom.xml | 11 + .../vpnservice/mdsalutil/ActionType.java | 66 +- .../vpnservice/mdsalutil/FlowInfoKey.java | 83 ++ .../vpnservice/mdsalutil/GroupInfoKey.java | 63 + .../vpnservice/mdsalutil/MDSALUtil.java | 2 +- .../vpnservice/mdsalutil/MatchFieldType.java | 45 + .../interfaces/IMdsalApiManager.java | 28 +- .../mdsalutil/internal/MDSALManager.java | 69 +- .../mdsalutil/internal/MDSALUtilProvider.java | 20 +- .../mdsalutil/internal/NotifyTask.java | 24 + .../vpnservice/nexthopmgr/NexthopManager.java | 23 +- pom.xml | 1 + 65 files changed, 5936 insertions(+), 45 deletions(-) create mode 100644 elanmanager/elanmanager-api/pom.xml create mode 100644 elanmanager/elanmanager-api/src/main/java/org/opendaylight/elanmanager/api/IElanService.java create mode 100644 elanmanager/elanmanager-api/src/main/java/org/opendaylight/elanmanager/exceptions/MacNotFoundException.java create mode 100644 elanmanager/elanmanager-api/src/main/yang/elan-statistics.yang create mode 100644 elanmanager/elanmanager-api/src/main/yang/elan.yang create mode 100644 elanmanager/elanmanager-api/src/main/yang/elanmanager-api.yang create mode 100644 elanmanager/elanmanager-impl/pom.xml create mode 100644 elanmanager/elanmanager-impl/src/main/config/default-config.xml create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanAdd.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanDelete.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanGet.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanInterfaceAdd.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanInterfaceDelete.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanInterfaceGet.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanInterfaceUpdate.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanMacTableFlush.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanMacTableGet.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanUpdate.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/StaticMacAdd.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/StaticMacDelete.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanForwardingEntriesHandler.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanInstanceManager.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanInterfaceManager.java create mode 100755 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanItmEventListener.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanNodeListener.java create mode 100755 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanPacketInHandler.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanServiceProvider.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanSmacFlowEventListener.java create mode 100755 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/statisitcs/ElanStatisticsImpl.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/utils/ElanCLIUtils.java create mode 100755 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/utils/ElanConstants.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/utils/ElanUtils.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/elanservice/impl/rev150216/ElanServiceImplModule.java create mode 100644 elanmanager/elanmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/elanservice/impl/rev150216/ElanServiceImplModuleFactory.java create mode 100644 elanmanager/elanmanager-impl/src/main/resources/OSGI-INF/blueprint/blueprint.xml create mode 100644 elanmanager/elanmanager-impl/src/main/yang/elanservice-impl.yang create mode 100644 elanmanager/pom.xml create mode 100644 interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/exceptions/InterfaceAlreadyExistsException.java create mode 100644 interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/exceptions/InterfaceNotFoundException.java create mode 100644 interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/exceptions/InterfaceServiceNotFoundException.java create mode 100644 interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/globals/IfmConstants.java create mode 100644 interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/globals/InterfaceInfo.java create mode 100644 interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/globals/InterfaceServiceUtil.java create mode 100644 interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/globals/LogicalGroupInterfaceInfo.java create mode 100644 interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/globals/VlanInterfaceInfo.java create mode 100644 interfacemgr/interfacemgr-api/src/main/yang/interface-statistics.yang mode change 100644 => 100755 mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/ActionType.java create mode 100644 mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/FlowInfoKey.java create mode 100644 mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/GroupInfoKey.java mode change 100644 => 100755 mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MatchFieldType.java create mode 100644 mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/NotifyTask.java mode change 100644 => 100755 nexthopmgr/nexthopmgr-impl/src/main/java/org/opendaylight/vpnservice/nexthopmgr/NexthopManager.java diff --git a/elanmanager/elanmanager-api/pom.xml b/elanmanager/elanmanager-api/pom.xml new file mode 100644 index 00000000..af6914ab --- /dev/null +++ b/elanmanager/elanmanager-api/pom.xml @@ -0,0 +1,63 @@ + + + + + org.opendaylight.vpnservice + config-parent + 0.2.0-SNAPSHOT + ../../commons/config-parent + + + 4.0.0 + org.opendaylight.vpnservice + elanmanager-api + ${vpnservices.version} + bundle + + + + org.opendaylight.mdsal + yang-binding + + + org.opendaylight.mdsal.model + yang-ext + + + org.opendaylight.mdsal.model + ietf-inet-types + + + org.opendaylight.mdsal.model + ietf-yang-types + + + org.opendaylight.mdsal.model + ietf-interfaces + + + org.opendaylight.mdsal.model + iana-if-type-2014-05-08 + + + org.opendaylight.controller.model + model-inventory + ${controller.mdsal.version} + + + ${project.groupId} + interfacemgr-api + ${project.version} + + + org.opendaylight.controller + config-api + + + diff --git a/elanmanager/elanmanager-api/src/main/java/org/opendaylight/elanmanager/api/IElanService.java b/elanmanager/elanmanager-api/src/main/java/org/opendaylight/elanmanager/api/IElanService.java new file mode 100644 index 00000000..a6f51b49 --- /dev/null +++ b/elanmanager/elanmanager-api/src/main/java/org/opendaylight/elanmanager/api/IElanService.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.elanmanager.api; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntry; +import org.opendaylight.elanmanager.exceptions.MacNotFoundException; + +import java.util.Collection; +import java.util.List; + +public interface IElanService { + public boolean createElanInstance(String elanInstanceName, long MacTimeout, String description); + public void updateElanInstance(String elanInstanceName, long newMacTimout, String newDescription); + public boolean deleteElanInstance(String elanInstanceName); + + public void addElanInterface(String elanInstanceName, String interfaceName, List staticMacAddresses, String description); + public void updateElanInterface(String elanInstanceName, String interfaceName, List updatedStaticMacAddresses, String newDescription); + public void deleteElanInterface(String elanInstanceName, String interfaceName); + + public void addStaticMacAddress(String elanInstanceName, String interfaceName, String macAddress); + public void deleteStaticMacAddress(String elanInstanceName, String interfaceName, String macAddress) throws MacNotFoundException; + public Collection getElanMacTable(String elanInstanceName); + public void flushMACTable(String elanInstanceName); + public ElanInstance getElanInstance(String elanInstanceName); + public List getElanInstances(); + public List getElanInterfaces(String elanInstanceName); + +} diff --git a/elanmanager/elanmanager-api/src/main/java/org/opendaylight/elanmanager/exceptions/MacNotFoundException.java b/elanmanager/elanmanager-api/src/main/java/org/opendaylight/elanmanager/exceptions/MacNotFoundException.java new file mode 100644 index 00000000..fc534715 --- /dev/null +++ b/elanmanager/elanmanager-api/src/main/java/org/opendaylight/elanmanager/exceptions/MacNotFoundException.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.elanmanager.exceptions; + +public class MacNotFoundException extends Exception { + + private static final long serialVersionUID = 1L; + + public MacNotFoundException() { + + } + + public MacNotFoundException(String message) { + super(message); + } +} diff --git a/elanmanager/elanmanager-api/src/main/yang/elan-statistics.yang b/elanmanager/elanmanager-api/src/main/yang/elan-statistics.yang new file mode 100644 index 00000000..ff81823c --- /dev/null +++ b/elanmanager/elanmanager-api/src/main/yang/elan-statistics.yang @@ -0,0 +1,32 @@ +module elan-statistics { + namespace "urn:opendaylight:vpnservice:elan:statistics"; + prefix elan-stats; + + import ietf-interfaces { + prefix if; + } + + import interface-statistics { + prefix if-stats; + } + + revision "2015-08-24" { + description "YANG model describes rpc to retrieve the different + ELAN interface statistics ie. packet/byte counts"; + } + + rpc get-elan-interface-statistics { + input { + leaf interface-name { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + } + } + output { + container stat-result { + uses if-stats:stat-reply; + } + } + } +} diff --git a/elanmanager/elanmanager-api/src/main/yang/elan.yang b/elanmanager/elanmanager-api/src/main/yang/elan.yang new file mode 100644 index 00000000..5b4b1055 --- /dev/null +++ b/elanmanager/elanmanager-api/src/main/yang/elan.yang @@ -0,0 +1,240 @@ +module elan { + + namespace "urn:opendaylight:vpnservice:elan"; + prefix elan; + + import ietf-interfaces { + prefix if; + } + + import ietf-yang-types { + prefix yang; + } + + + revision "2015-06-02" { + description "elan module"; + } + + /* + * elan instance view. + */ + container elan-instances { + description + "elan instances configuration parameters. + elan instances support both the VLAN and VNI based elans."; + + list elan-instance { + max-elements "unbounded"; + min-elements "0"; + key "elan-instance-name"; + description + "Specifies the name of the elan instance. It is a string of 1 to 31 + case-sensitive characters."; + leaf elan-instance-name { + type string; + description + "The name of the elan-instance."; + } + leaf elan-tag { + type uint32; + description "ELAN unique identifier which is unique across all the tenants. This will be created internally and if provided, the value will be discarded."; + } + leaf mac-timeout { + type uint32 { + range "0..65535"; + } + description "MAC Table entry ageing time in seconds. A value of 0 will indicate that the MAC will never expire."; + } + leaf description { + description + "A textual description of elan instance, the elan instance description + helps users memorize the elan instance."; + + type string { + length "1..254"; + } + } + } + } + + /* + * Binding Interfaces to a elan Instance. + */ + container elan-interfaces { + description + "elan is enabled on interfaces."; + + list elan-interface { + key "name"; + max-elements "unbounded"; + min-elements "0"; + leaf name { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + } + leaf elan-instance-name { + mandatory true; + type string; + } + leaf-list static-mac-entries { + type yang:phys-address; + } + leaf description { + description + "A textual description of elan port, the elan port description + helps users memorize the elan port."; + + type string { + length "1..254"; + } + } + } + } + + /* operational data stores */ + container elan-state { + config false; + description + "operational state of elans."; + + list elan { + key "name"; + description "The list of interfaces on the device."; + max-elements "unbounded"; + min-elements "0"; + leaf name { + type string; + description + "The name of the elan-instance."; + } + leaf-list elan-interfaces{ + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + description "Interfaces connected to this elan instance."; + } + } + } + + grouping forwarding-entries { + description "Details of the MAC entries"; + + list mac-entry { + key "mac-address"; + description "Details of a MAC address"; + max-elements "unbounded"; + min-elements "0"; + + leaf mac-address { + type yang:phys-address; + } + + leaf interface { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + } + + leaf controllerLearnedForwardingEntryTimestamp { + type uint64; + } + + leaf isStaticAddress { + type boolean; + } + } + } + + container elan-forwarding-tables { + config false; + description + "MAC tables for each elan instance"; + + list mac-table { + max-elements "unbounded"; + min-elements "0"; + key "elan-instance-name"; + description + "Specifies the name of the elan instance. It is a string of 1 to 31 + case-sensitive characters."; + + leaf elan-instance-name { + type string; + description + "The name of the elan-instance."; + } + + uses forwarding-entries; + } + } + + container elan-interface-forwarding-entries { + config false; + + list elan-interface-mac { + key "elan-interface"; + description "All the MAC addresses learned on a particular elan interface"; + max-elements "unbounded"; + min-elements "0"; + leaf elan-interface { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + } + + uses forwarding-entries; + } + } + + container elan-dpn-interfaces { + config false; + + list elan-dpn-interfaces-list { + key "elan-instance-name"; + description "All the dpns of this elan and all the ports of the corresponding dpns"; + max-elements "unbounded"; + min-elements "0"; + + leaf elan-instance-name { + type string; + description "The name of the elan-instance."; + } + + list dpn-interfaces { + key "dp-id"; + description "A DPN in which the elan spans across"; + max-elements "unbounded"; + min-elements "0"; + + leaf dp-id { + type uint64; + } + + leaf-list interfaces { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + } + } + } + } + + container elan-tag-name-map { + config false; + + list elan-tag-name { + key elan-tag; + leaf elan-tag { + type uint32; + } + + leaf name { + type string; + description + "The name of the elan-instance."; + } + } + } +} \ No newline at end of file diff --git a/elanmanager/elanmanager-api/src/main/yang/elanmanager-api.yang b/elanmanager/elanmanager-api/src/main/yang/elanmanager-api.yang new file mode 100644 index 00000000..e0508bab --- /dev/null +++ b/elanmanager/elanmanager-api/src/main/yang/elanmanager-api.yang @@ -0,0 +1,20 @@ +module elanmanager-api { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:elanmanager:api"; + prefix "elanmanager-api"; + + import config { prefix config; revision-date 2013-04-05; } + + description + "Service definition for elanmanager project"; + + revision "2015-07-07" { + description + "Initial revision"; + } + + identity elanmanager-api { + base "config:service-type"; + config:java-class "org.opendaylight.elanmanager.api.IElanService"; + } +} \ No newline at end of file diff --git a/elanmanager/elanmanager-impl/pom.xml b/elanmanager/elanmanager-impl/pom.xml new file mode 100644 index 00000000..3939c93a --- /dev/null +++ b/elanmanager/elanmanager-impl/pom.xml @@ -0,0 +1,60 @@ + + + + + + org.opendaylight.vpnservice + config-parent + 0.2.0-SNAPSHOT + ../../commons/config-parent + + + 4.0.0 + org.opendaylight.vpnservice + elanmanager-impl + ${vpnservices.version} + bundle + + + ${project.groupId} + elanmanager-api + ${vpnservices.version} + + + ${project.groupId} + mdsalutil-api + ${vpnservices.version} + + + ${project.groupId} + interfacemgr-api + ${vpnservices.version} + + + org.opendaylight.vpnservice + idmanager-api + ${vpnservices.version} + + + org.opendaylight.vpnservice + itm-api + ${vpnservices.version} + + + org.opendaylight.controller + sal-binding-broker-impl + + + org.apache.karaf.shell + org.apache.karaf.shell.console + 3.0.3 + + + + diff --git a/elanmanager/elanmanager-impl/src/main/config/default-config.xml b/elanmanager/elanmanager-impl/src/main/config/default-config.xml new file mode 100644 index 00000000..f4f49916 --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/config/default-config.xml @@ -0,0 +1,63 @@ + + + + + + urn:opendaylight:params:xml:ns:yang:elanservice:impl?module=elanservice-impl&revision=2015-02-16 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28 + urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&revision=2013-10-28 + urn:opendaylight:params:xml:ns:yang:mdsalutil:api?module=odl-mdsalutil&revision=2015-04-10 + urn:opendaylight:vpnservice:itm?module=itm&revision=2015-07-01 + urn:opendaylight:vpnservice:interfacemgr?module=odl-interface&revision=2015-03-31 + + + + + + + prefix:elanservice-impl + elanservice-default + + binding:binding-broker-osgi-registry + binding-osgi-broker + + + binding:binding-rpc-registry + binding-rpc-broker + + + mdsalutil:odl-mdsalutil + mdsalutil-service + + + odlif:odl-interface + interfacemgr-service + + + itm:itm + itm + + + bindingimpl:binding-new-notification-service + binding-notification-adapter + + + + + + prefix:elanmanager-api + + elanmanager + /modules/module[type='elanservice-impl'][name='elanservice-default'] + + + + + + \ No newline at end of file diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanAdd.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanAdd.java new file mode 100644 index 00000000..440710e8 --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanAdd.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.cli; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.opendaylight.elanmanager.api.IElanService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Command(scope = "elan", name = "add", description = "adding Elan Instance") +public class ElanAdd extends OsgiCommandSupport { + + @Argument(index = 0, name = "elanName", description = "ELAN-NAME", required = true, multiValued = false) + private String elanName; + @Argument(index = 1, name = "macTimeOut", description = "MAC Time-Out", required = false, multiValued = false) + private long macTimeOut = 30; + @Argument(index = 2, name = "elanDescr", description = "ELAN-Description", required = false, multiValued = false) + private String elanDescr; + private static final Logger logger = LoggerFactory.getLogger(ElanAdd.class); + private IElanService elanProvider; + public static int MAX_LENGTH = 31; + + public void setElanProvider(IElanService elanServiceProvider) { + this.elanProvider = elanServiceProvider; + } + + @Override + protected Object doExecute() { + try { + logger.debug("Executing create ElanInstance command" + "\t" + elanName + "\t" + macTimeOut + "\t" + elanDescr + "\t"); + if(elanName.length()<= MAX_LENGTH) { + boolean isSuccess = elanProvider.createElanInstance(elanName, macTimeOut, elanDescr); + if (isSuccess) { + System.out.println("Elan Instance is created successfully"); + } + } else { + System.out.println("Failed to create Elan Instance, max length is allowed 1 .. 31"); + } + } catch (Exception e) { + logger.error("Elan Instance failed to create {}", e); + e.printStackTrace(); + } + return null; + } +} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanDelete.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanDelete.java new file mode 100644 index 00000000..46be93e3 --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanDelete.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.cli; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.opendaylight.elanmanager.api.IElanService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Command(scope = "elan", name = "delete", description = "Deleting the Elan Instance") +public class ElanDelete extends OsgiCommandSupport { + + @Argument(index = 0, name = "elanName", description = "ELAN-NAME", required = true, multiValued = false) + private String elanName; + + private static final Logger logger = LoggerFactory.getLogger(ElanDelete.class); + private IElanService elanProvider; + + public void setElanProvider(IElanService elanServiceProvider) { + this.elanProvider = elanServiceProvider; + } + + @Override + protected Object doExecute() { + try { + logger.debug("Executing the Deletion of ElanInstance command" + "\t" + elanName + "\t"); + boolean isSuccess = elanProvider.deleteElanInstance(elanName); + if(isSuccess) { + System.out.println("Elan Instance deleted successfully"); + } else { + System.out.println("ELan Instance failed to delete"); + } + } catch (Exception e) { + logger.error("Failed to delete Elan Instance {}", e); + e.printStackTrace(); + } + return null; + } +} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanGet.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanGet.java new file mode 100644 index 00000000..27a4103a --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanGet.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.cli; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.opendaylight.elanmanager.api.IElanService; +import org.opendaylight.vpnservice.elan.utils.ElanCLIUtils; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +@Command(scope = "elan", name = "show", description = "display Elan Instance") +public class ElanGet extends OsgiCommandSupport { + + private static final Logger logger = LoggerFactory.getLogger(ElanGet.class); + + @Argument(index = 0, name = "elanName", description = "ELAN-NAME", required = false, multiValued = false) + private String elanName; + private IElanService elanProvider; + + public void setElanProvider(IElanService elanServiceProvider) { + this.elanProvider = elanServiceProvider; + } + + @Override + protected Object doExecute() { + try { + logger.debug("Executing Get ElanInstance command" + "\t" + elanName + "\t"); + if(elanName != null) { + ElanInstance elanInstance = elanProvider.getElanInstance(elanName); + if (elanInstance == null) { + System.out.println("No Elan Instance present with name:" + elanName); + } else { + System.out.println(getElanHeaderOutput()); + System.out.println(String.format(ElanCLIUtils.ELAN_CLI_FORMAT, elanInstance.getElanInstanceName(), elanInstance.getMacTimeout(), elanInstance.getElanTag(), elanInstance.getDescription())); + } + + } else { + List elanInstanceList = elanProvider.getElanInstances(); + if(elanInstanceList != null && !elanInstanceList.isEmpty()) { + System.out.println(getElanHeaderOutput()); + for(ElanInstance elanInstance : elanInstanceList) { + System.out.println(String.format(ElanCLIUtils.ELAN_CLI_FORMAT, elanInstance.getElanInstanceName(), elanInstance.getMacTimeout(), elanInstance.getElanTag(), elanInstance.getDescription())); + } + } else { + System.out.println("No Elan Instances are present"); + } + + } + } catch (Exception e) { + logger.error("Elan Instance failed to get {}", e); + e.printStackTrace(); + } + return null; + } + + private Object getElanHeaderOutput() { + StringBuilder headerBuilder = new StringBuilder(); + headerBuilder.append(String.format(ElanCLIUtils.ELAN_CLI_FORMAT, "Elan Instance", "Mac-TimeOut", "Tag")); + headerBuilder.append('\n'); + headerBuilder.append(ElanCLIUtils.HEADER_UNDERLINE); + return headerBuilder.toString(); + } +} + diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanInterfaceAdd.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanInterfaceAdd.java new file mode 100644 index 00000000..ff1ad192 --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanInterfaceAdd.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.cli; + +import java.math.BigInteger; +import java.util.List; + +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.commands.Option; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.util.concurrent.Futures; +import org.opendaylight.elanmanager.api.IElanService; + +@Command(scope = "elanInterface", name = "add", description = "adding Elan Interface") +public class ElanInterfaceAdd extends OsgiCommandSupport { + + @Argument(index = 0, name = "elanName", description = "ELAN-NAME", required = true, multiValued = false) + private String elanName; + @Argument(index = 1, name = "interfaceName", description = "InterfaceName", required = true, multiValued = false) + private String interfaceName; + @Argument(index = 2, name = "staticMacAddresses", description = "StaticMacAddresses", required = false, multiValued = true) + private List staticMacAddresses; + @Argument(index = 3, name = "elanInterfaceDescr", description = "ELAN Interface-Description", required = false, multiValued = false) + private String elanInterfaceDescr; + private static final Logger logger = LoggerFactory.getLogger(ElanInterfaceAdd.class); + private IElanService elanProvider; + + public void setElanProvider(IElanService elanServiceProvider) { + this.elanProvider = elanServiceProvider; + } + + @Override + protected Object doExecute() { + try { + logger.debug("Executing create ElanInterface command" + "\t" + elanName + "\t" + interfaceName + "\t" + staticMacAddresses + "\t" + + elanInterfaceDescr + "\t"); + elanProvider.addElanInterface(elanName, interfaceName, staticMacAddresses, elanInterfaceDescr); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanInterfaceDelete.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanInterfaceDelete.java new file mode 100644 index 00000000..6a3f93fa --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanInterfaceDelete.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.cli; + +import java.math.BigInteger; +import java.util.List; + +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.commands.Option; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.util.concurrent.Futures; +import org.opendaylight.elanmanager.api.IElanService; + +@Command(scope = "elanInterface", name = "delete", description = "deleting Elan Interface") +public class ElanInterfaceDelete extends OsgiCommandSupport { + + @Argument(index = 0, name = "elanName", description = "ELAN-NAME", required = true, multiValued = false) + private String elanName; + @Argument(index = 1, name = "interfaceName", description = "InterfaceName", required = true, multiValued = false) + private String interfaceName; + private static final Logger logger = LoggerFactory.getLogger(ElanInterfaceDelete.class); + private IElanService elanProvider; + + public void setElanProvider(IElanService elanServiceProvider) { + this.elanProvider = elanServiceProvider; + } + + @Override + protected Object doExecute() { + try { + logger.debug("Deleting ElanInterface command" + "\t" + elanName + "\t" + interfaceName + "\t"); + elanProvider.deleteElanInterface(elanName, interfaceName); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} \ No newline at end of file diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanInterfaceGet.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanInterfaceGet.java new file mode 100644 index 00000000..a07f3de8 --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanInterfaceGet.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.cli; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.opendaylight.elanmanager.api.IElanService; +import org.opendaylight.vpnservice.elan.utils.ElanCLIUtils; +import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo; +import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +@Command(scope = "elanInterface", name = "show", description = "display Elan Interfaces for the ElanInstance") +public class ElanInterfaceGet extends OsgiCommandSupport { + + private static final Logger logger = LoggerFactory.getLogger(ElanInterfaceGet.class); + + @Argument(index = 0, name = "elanName", description = "ELAN-NAME", required = false, multiValued = false) + private String elanName; + private IInterfaceManager interfaceManager; + public static int MAX_LENGTH = 31; + private IElanService elanProvider; + public static boolean isDisplay = true; + + public void setElanProvider(IElanService elanServiceProvider) { + this.elanProvider = elanServiceProvider; + } + + public void setInterfaceManager(IInterfaceManager interfaceManager) { + this.interfaceManager = interfaceManager; + } + + @Override + protected Object doExecute() { + try { + logger.debug("Executing Get ElanInterface command for the corresponding Elan Instance" + "\t" + elanName + "\t"); + if(elanName != null) { + ElanInstance elanInstance = elanProvider.getElanInstance(elanName); + List elanInterfaces = elanProvider.getElanInterfaces(elanName); + if (elanInterfaces == null) { + System.out.println("No Elan Interfaces present for ELan Instance:" + elanName); + return null; + } + System.out.println(getElanInterfaceHeaderOutput()); + displayInterfaces(elanInstance, elanInterfaces); + + } else { + List elanInstances = elanProvider.getElanInstances(); + if(!elanInstances.isEmpty()) { + System.out.println(getElanInterfaceHeaderOutput()); + for(ElanInstance elanInstance : elanInstances) { + List elanInterfaces = elanProvider.getElanInterfaces(elanInstance.getElanInstanceName()); + displayInterfaces(elanInstance, elanInterfaces); + System.out.println("\n"); + } + } + + } + } catch (Exception e) { + logger.error("Elan Instance failed to get {}", e); + e.printStackTrace(); + } + return null; + } + + private Object getElanInterfaceHeaderOutput() { + StringBuilder headerBuilder = new StringBuilder(); + headerBuilder.append(String.format(ElanCLIUtils.ELAN_INTERFACE_CLI_FORMAT, "ElanInstance/Tag", "ElanInterface/Tag", "OpState" , "AdminState")); + headerBuilder.append('\n'); + headerBuilder.append(ElanCLIUtils.HEADER_UNDERLINE); + return headerBuilder.toString(); + } + + private void displayInterfaces(ElanInstance elanInstance, List interfaceList) { + if(!interfaceList.isEmpty()) { + for (String elanInterface : interfaceList) + { + InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(elanInterface); + if (interfaceInfo != null) { + System.out.println(String.format(ElanCLIUtils.ELAN_INTERFACE_CLI_FORMAT, elanInstance.getElanInstanceName()+"/"+elanInstance.getElanTag(), elanInterface+"/"+interfaceInfo.getInterfaceTag(), interfaceInfo.getOpState(), interfaceInfo.getAdminState())); + } + } + } + } +} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanInterfaceUpdate.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanInterfaceUpdate.java new file mode 100644 index 00000000..d4526feb --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanInterfaceUpdate.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.cli; + +import java.math.BigInteger; +import java.util.List; + +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.commands.Option; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.util.concurrent.Futures; +import org.opendaylight.elanmanager.api.IElanService; + +@Command(scope = "elanInterface", name = "update", description = "updating Elan Interface") +public class ElanInterfaceUpdate extends OsgiCommandSupport { + + @Argument(index = 0, name = "elanName", description = "ELAN-NAME", required = true, multiValued = false) + private String elanName; + @Argument(index = 1, name = "interfaceName", description = "InterfaceName", required = true, multiValued = false) + private String interfaceName; + @Argument(index = 2, name = "staticMacAddresses", description = "StaticMacAddresses", required = false, multiValued = true) + private List staticMacAddresses; + @Argument(index = 3, name = "elanInterfaceDescr", description = "ELAN Interface-Description", required = false, multiValued = false) + private String elanInterfaceDescr; + private static final Logger logger = LoggerFactory.getLogger(ElanInterfaceUpdate.class); + private IElanService elanProvider; + + public void setElanProvider(IElanService elanServiceProvider) { + this.elanProvider = elanServiceProvider; + } + + @Override + protected Object doExecute() { + try { + logger.debug("Executing updating ElanInterface command" + "\t" + elanName + "\t" + interfaceName + "\t" + staticMacAddresses + "\t" + + elanInterfaceDescr + "\t"); + elanProvider.updateElanInterface(elanName, interfaceName, staticMacAddresses, elanInterfaceDescr); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} + diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanMacTableFlush.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanMacTableFlush.java new file mode 100644 index 00000000..84483474 --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanMacTableFlush.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.cli; + +import java.math.BigInteger; +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.commands.Option; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.util.concurrent.Futures; +import org.opendaylight.elanmanager.api.IElanService; + +@Command(scope = "elanmactable", name = "flush", description = "Flush the Mac Entries for Elan Instance") +public class ElanMacTableFlush extends OsgiCommandSupport { + + @Argument(index = 0, name = "elanName", description = "ELAN-NAME", required = true, multiValued = false) + private String elanName; + + private static final Logger logger = LoggerFactory.getLogger(ElanMacTableFlush.class); + private IElanService elanProvider; + + public void setElanProvider(IElanService elanServiceProvider) { + this.elanProvider = elanServiceProvider; + } + + @Override + protected Object doExecute() { + try { + logger.debug("Executing create ElanInstance command" + "\t" + elanName + "\t"); + elanProvider.flushMACTable(elanName); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanMacTableGet.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanMacTableGet.java new file mode 100644 index 00000000..2b4a6622 --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanMacTableGet.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.cli; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.opendaylight.elanmanager.api.IElanService; +import org.opendaylight.vpnservice.elan.utils.ElanCLIUtils; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.SimpleDateFormat; +import java.util.Collection; +import java.util.Date; + +@Command(scope = "elanmactable", name = "show", description = "get Elan Mac table") +public class ElanMacTableGet extends OsgiCommandSupport { + + private static final Logger logger = LoggerFactory.getLogger(ElanMacTableGet.class); + + @Argument(index = 0, name = "elanName", description = "ELAN-NAME", required = true, multiValued = false) + private String elanName; + private IElanService elanProvider; + + public void setElanProvider(IElanService elanServiceProvider) { + this.elanProvider = elanServiceProvider; + } + + @Override + protected Object doExecute() { + try { + logger.debug("Executing updating ElanInterface command" + "\t"); + Collection macTables = elanProvider.getElanMacTable(elanName); + if(!macTables.isEmpty()) { + SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yy:HH:mm:SS"); + System.out.println(getMacTableHeaderOutput()); + System.out.println(elanName); + for(MacEntry mac : macTables) { + boolean isStatic = mac.isIsStaticAddress(); + System.out.println(String.format(ElanCLIUtils.MAC_TABLE_CLI_FORMAT, "", mac.getInterface(), mac.getMacAddress().getValue(), "")); + System.out.println(String.format(ElanCLIUtils.MAC_TABLE_CLI_FORMAT, "", isStatic, "", isStatic? "-" : formatter.format(new Date(mac.getControllerLearnedForwardingEntryTimestamp().longValue())))); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + private Object getMacTableHeaderOutput() { + StringBuilder headerBuilder = new StringBuilder(); + headerBuilder.append(String.format(ElanCLIUtils.MAC_TABLE_CLI_FORMAT, "Elan Instance", "Interface Name", "MacAddress", "")); + headerBuilder.append('\n'); + headerBuilder.append(String.format(ElanCLIUtils.MAC_TABLE_CLI_FORMAT, "", "Is Static?", "" , "TimeStamp")); + headerBuilder.append('\n'); + headerBuilder.append(ElanCLIUtils.HEADER_UNDERLINE); + return headerBuilder.toString(); + } +} + diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanUpdate.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanUpdate.java new file mode 100644 index 00000000..a40e667b --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/ElanUpdate.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.cli; + +import java.math.BigInteger; +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.commands.Option; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.util.concurrent.Futures; +import org.opendaylight.elanmanager.api.IElanService; + +@Command(scope = "elan", name = "update", description = "updating the Elan Instance") +public class ElanUpdate extends OsgiCommandSupport { + + @Argument(index = 0, name = "elanName", description = "ELAN-NAME", required = true, multiValued = false) + private String elanName; + @Argument(index = 1, name = "macTimeOut", description = "MAC Time-Out", required = false, multiValued = false) + private long macTimeOut; + @Argument(index = 2, name = "elanDescr", description = "ELAN-Description", required = false, multiValued = false) + private String elanDescr; + private static final Logger logger = LoggerFactory.getLogger(ElanUpdate.class); + private IElanService elanProvider; + + public void setElanProvider(IElanService elanServiceProvider) { + this.elanProvider = elanServiceProvider; + } + + @Override + protected Object doExecute() { + try { + logger.debug("Updating the ElanInstance command" + "\t" + elanName + "\t" + macTimeOut + "\t" + elanDescr + "\t"); + elanProvider.updateElanInstance(elanName, macTimeOut, elanDescr); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/StaticMacAdd.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/StaticMacAdd.java new file mode 100644 index 00000000..3eb4a2ec --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/StaticMacAdd.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.cli; + +import java.math.BigInteger; +import java.util.List; + +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.commands.Option; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.util.concurrent.Futures; +import org.opendaylight.elanmanager.api.IElanService; + +@Command(scope = "staticMac", name = "add", description = "adding Static Mac Address") +public class StaticMacAdd extends OsgiCommandSupport { + + @Argument(index = 0, name = "elanName", description = "ELAN-NAME", required = true, multiValued = false) + private String elanName; + @Argument(index = 1, name = "interfaceName", description = "InterfaceName", required = true, multiValued = false) + private String interfaceName; + @Argument(index = 2, name = "staticMacAddress", description = "StaticMacAddress", required = true, multiValued = false) + private String staticMacAddress; + private static final Logger logger = LoggerFactory.getLogger(StaticMacAdd.class); + private IElanService elanProvider; + + public void setElanProvider(IElanService elanServiceProvider) { + this.elanProvider = elanServiceProvider; + } + + @Override + protected Object doExecute() { + try { + logger.debug("Executing create ElanInterface command" + "\t" + elanName + "\t" + interfaceName + "\t" + staticMacAddress + "\t"); + elanProvider.addStaticMacAddress(elanName, interfaceName, staticMacAddress); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/StaticMacDelete.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/StaticMacDelete.java new file mode 100644 index 00000000..4789437d --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/cli/StaticMacDelete.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.cli; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.console.OsgiCommandSupport; +import org.opendaylight.elanmanager.api.IElanService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Command(scope = "staticMac", name = "delete", description = "deleting Static Mac Address") +public class StaticMacDelete extends OsgiCommandSupport { + + @Argument(index = 0, name = "elanName", description = "ELAN-NAME", required = true, multiValued = false) + private String elanName; + @Argument(index = 1, name = "interfaceName", description = "InterfaceName", required = true, multiValued = false) + private String interfaceName; + @Argument(index = 2, name = "staticMacAddress", description = "StaticMacAddress", required = true, multiValued = false) + private String staticMacAddress; + private static final Logger logger = LoggerFactory.getLogger(StaticMacDelete.class); + private IElanService elanProvider; + + public void setElanProvider(IElanService elanServiceProvider) { + this.elanProvider = elanServiceProvider; + } + + @Override + protected Object doExecute() { + try { + logger.debug("Executing create ElanInterface command" + "\t" + elanName + "\t" + interfaceName + "\t" + staticMacAddress + "\t"); + elanProvider.deleteStaticMacAddress(elanName, interfaceName, staticMacAddress); + } catch (Exception e) { + + e.printStackTrace(); + } + return null; + } +} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanForwardingEntriesHandler.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanForwardingEntriesHandler.java new file mode 100644 index 00000000..4acb68d1 --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanForwardingEntriesHandler.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.internal; + + +import com.google.common.base.Optional; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.vpnservice.elan.utils.ElanUtils; +import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo; +import org.opendaylight.vpnservice.itm.api.IITMProvider; +import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener; +import org.opendaylight.vpnservice.mdsalutil.MDSALUtil; +import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanInterfaces; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntryBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntryKey; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class ElanForwardingEntriesHandler extends AbstractDataChangeListener implements AutoCloseable { + private DataBroker broker; + private ListenerRegistration listenerRegistration; + + private IMdsalApiManager mdsalManager; + + private IITMProvider itmManager; + + private static final Logger logger = LoggerFactory.getLogger(ElanForwardingEntriesHandler.class); + + + public ElanForwardingEntriesHandler(DataBroker db, IMdsalApiManager mdsalManager){ + super(ElanInterface.class); + this.broker = db; + this.mdsalManager = mdsalManager; + } + + public void setIITMManager(IITMProvider itmManager) { + this.itmManager = itmManager; + } + + private InstanceIdentifier getWildCardPath() { + return InstanceIdentifier.create(ElanInterfaces.class).child(ElanInterface.class); + } + + public void updateElanInterfaceForwardingTablesList(String elanInstanceName, String interfaceName, String existingInterfaceName, MacEntry mac) { + if(existingInterfaceName == interfaceName) { + logger.error(String.format("Static MAC address %s has already been added for the same ElanInstance %s on the same Logical Interface Port %s." + + " No operation will be done.", mac.getMacAddress().toString(), elanInstanceName, interfaceName)); + } else { + logger.warn(String.format("Static MAC address %s had already been added for ElanInstance %s on Logical Interface Port %s. " + + "This would be considered as MAC movement scenario and old static mac will be removed and new static MAC will be added" + + "for ElanInstance %s on Logical Interface Port %s", mac.getMacAddress().toString(), elanInstanceName, interfaceName, elanInstanceName, interfaceName)); + //Update the ElanInterface Forwarding Container & ElanForwarding Container + deleteElanInterfaceForwardingTablesList(existingInterfaceName, mac); + createElanInterfaceForwardingTablesList(interfaceName, mac); + updateElanForwardingTablesList(elanInstanceName, interfaceName, mac); + } + + } + + public void addElanInterfaceForwardingTableList(ElanInstance elanInstance, String interfaceName, PhysAddress physAddress) { + MacEntry macEntry = new MacEntryBuilder().setIsStaticAddress(true).setMacAddress(physAddress).setInterface(interfaceName).setKey(new MacEntryKey(physAddress)).build(); + createElanForwardingTablesList(elanInstance.getElanInstanceName(), macEntry); + createElanInterfaceForwardingTablesList(interfaceName, macEntry); + } + + public void deleteElanInterfaceForwardingTablesList(String interfaceName, MacEntry mac) { + InstanceIdentifier existingMacEntryId = ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, mac.getMacAddress()); + MacEntry existingInterfaceMacEntry = ElanUtils.getInterfaceMacEntriesOperationalDataPathFromId(existingMacEntryId); + if(existingInterfaceMacEntry != null) { + ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, existingMacEntryId); + } + } + + public void createElanInterfaceForwardingTablesList(String interfaceName, MacEntry mac) { + InstanceIdentifier existingMacEntryId = ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, mac.getMacAddress()); + MacEntry existingInterfaceMacEntry = ElanUtils.getInterfaceMacEntriesOperationalDataPathFromId(existingMacEntryId); + if(existingInterfaceMacEntry == null) { + MacEntry macEntry = new MacEntryBuilder().setMacAddress(mac.getMacAddress()).setInterface(interfaceName).setIsStaticAddress(true).setKey(new MacEntryKey(mac.getMacAddress())).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, existingMacEntryId, macEntry); + + } + } + + public void updateElanForwardingTablesList(String elanName, String interfaceName, MacEntry mac) { + InstanceIdentifier macEntryId = ElanUtils.getMacEntryOperationalDataPath(elanName, mac.getMacAddress()); + MacEntry existingMacEntry = ElanUtils.getMacEntryFromElanMacId(macEntryId); + if(existingMacEntry != null) { + ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, macEntryId); + MacEntry newMacEntry = new MacEntryBuilder().setInterface(interfaceName).setIsStaticAddress(true).setMacAddress(mac.getMacAddress()).setKey(new MacEntryKey(mac.getMacAddress())).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, macEntryId, newMacEntry); + } + } + + private void createElanForwardingTablesList(String elanName, MacEntry macEntry) { + InstanceIdentifier macEntryId = ElanUtils.getMacEntryOperationalDataPath(elanName, macEntry.getMacAddress()); + Optional existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macEntryId); + if(!existingMacEntry.isPresent()) { + MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, macEntryId, macEntry); + } + } + + public void deleteElanInterfaceForwardingEntries(ElanInstance elanInfo, InterfaceInfo interfaceInfo, MacEntry macEntry) { + InstanceIdentifier macEntryId = ElanUtils.getMacEntryOperationalDataPath(elanInfo.getElanInstanceName(), macEntry.getMacAddress()); + ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, macEntryId); + ElanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry); + } + + public void deleteElanInterfaceMacForwardingEntries(String interfaceName, PhysAddress physAddress) { + InstanceIdentifier macEntryId = ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress); + ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, macEntryId); + } + + @Override + protected void remove(InstanceIdentifier identifier, ElanInterface del) { + + } + + @Override + protected void update(InstanceIdentifier identifier, ElanInterface original, ElanInterface update) { + + } + + @Override + protected void add(InstanceIdentifier identifier, ElanInterface add) { + + } + + @Override + public void close() throws Exception { + if (listenerRegistration != null) { + try { + listenerRegistration.close(); + } catch (final Exception e) { + logger.error("Error when cleaning up Elan DataChangeListener.", e); + } + listenerRegistration = null; + } + } +} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanInstanceManager.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanInstanceManager.java new file mode 100644 index 00000000..d1aca50e --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanInstanceManager.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.internal; + +import com.google.common.base.Optional; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener; +import org.opendaylight.vpnservice.elan.utils.ElanConstants; +import org.opendaylight.vpnservice.elan.utils.ElanUtils; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanDpnInterfaces; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanInstances; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesListKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstanceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.state.Elan; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +public class ElanInstanceManager extends AbstractDataChangeListener implements AutoCloseable { + private DataBroker broker; + private static ElanInstanceManager elanInstanceManager = new ElanInstanceManager(); + private ListenerRegistration elanInstanceListenerRegistration; + private IdManagerService idManager; + private ElanInterfaceManager elanInterfaceManager; + + private static final Logger logger = LoggerFactory.getLogger(ElanInstanceManager.class); + + private ElanInstanceManager() { + super(ElanInstance.class); + + } + + public static ElanInstanceManager getElanInstanceManager() { + return elanInstanceManager; + } + + public void setIdManager(IdManagerService idManager) { + this.idManager = idManager; + } + + public void setDataBroker(DataBroker broker) { + this.broker = broker; + } + + public void setElanInterfaceManager(ElanInterfaceManager elanInterfaceManager) { + this.elanInterfaceManager = elanInterfaceManager; + } + + + public void registerListener() { + try { + elanInstanceListenerRegistration = broker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, + getElanInstanceWildcardPath(), ElanInstanceManager.this, DataChangeScope.SUBTREE); + } catch (final Exception e) { + logger.error("ELAN Instance DataChange listener registration failed !", e); + throw new IllegalStateException("ELAN Instance registration Listener failed.", e); + } + } + + private InstanceIdentifier getElanInstanceWildcardPath() { + return InstanceIdentifier.create(ElanInstances.class).child(ElanInstance.class); + } + + @Override + public void close() throws Exception { + if (elanInstanceListenerRegistration != null) { + elanInstanceListenerRegistration.close(); + } + } + + @Override + protected void remove(InstanceIdentifier identifier, ElanInstance del) { + logger.trace("Remove ElanInstance - Key: {}, value: {}", identifier, del); + String elanName = del.getElanInstanceName(); + //check the elan Instance present in the Operational DataStore + Elan existingElan = ElanUtils.getElanByName(elanName); + long elanTag = del.getElanTag(); + //Cleaning up the existing Elan Instance + if(existingElan != null) { + List elanInterfaces = existingElan.getElanInterfaces(); + if(elanInterfaces != null && !elanInterfaces.isEmpty()) { + for (String elanInterfaceName : elanInterfaces) { + InstanceIdentifier elanInterfaceId = ElanUtils.getElanInterfaceConfigurationDataPathId(elanInterfaceName); + elanInterfaceManager.removeElanInterface(del, elanInterfaceName); + ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION, elanInterfaceId); + } + } + ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName)); + ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, getElanDpnOperationDataPath(elanName)); + ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInfoEntriesOperationalDataPath(elanTag)); + } + // Release tag + ElanUtils.releaseId(idManager, ElanConstants.ELAN_ID_POOL_NAME, elanName); + + } + + @Override + protected void update(InstanceIdentifier identifier, ElanInstance original, ElanInstance update) { + if (original.getElanTag() == update.getElanTag()) { + return; + } else if (update.getElanTag() == null) { + // update the elan-Instance with new properties + if(original.getMacTimeout() == update.getMacTimeout() && original.getDescription().equalsIgnoreCase(update.getDescription())) { + return; + } + ElanUtils.UpdateOperationalDataStore(broker, idManager, update); + return; + } + elanInterfaceManager.handleunprocessedElanInterfaces(update); + } + + @Override + protected void add(InstanceIdentifier identifier, ElanInstance elanInstanceAdded) { + Elan elanInfo = ElanUtils.getElanByName(elanInstanceAdded.getElanInstanceName()); + if(elanInfo == null) { + ElanUtils.UpdateOperationalDataStore(broker, idManager, elanInstanceAdded); + } + } + + public ElanInstance getElanInstanceByName(String elanInstanceName) { + InstanceIdentifier elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName); + Optional elanInstance = ElanUtils.read(broker, LogicalDatastoreType.CONFIGURATION, elanIdentifierId); + if(elanInstance.isPresent()) { + return elanInstance.get(); + } + return null; + } + + public List getElanDPNByName(String elanInstanceName) { + InstanceIdentifier elanIdentifier = getElanDpnOperationDataPath(elanInstanceName); + Optional elanInstance = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanIdentifier); + if(elanInstance.isPresent()) { + ElanDpnInterfacesList elanDPNs = elanInstance.get(); + return elanDPNs.getDpnInterfaces(); + } + return null; + } + + private InstanceIdentifier getElanDpnOperationDataPath(String elanInstanceName) { + return InstanceIdentifier.builder(ElanDpnInterfaces.class).child(ElanDpnInterfacesList.class, new ElanDpnInterfacesListKey(elanInstanceName)).build(); + } + + private InstanceIdentifier getElanInstanceConfigurationDataPath(String elanInstanceName) { + return InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build(); + } +} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanInterfaceManager.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanInterfaceManager.java new file mode 100644 index 00000000..b933578d --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanInterfaceManager.java @@ -0,0 +1,1133 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.internal; + +import com.google.common.base.Optional; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.vpnservice.elan.utils.ElanConstants; +import org.opendaylight.vpnservice.elan.utils.ElanConstants; +import org.opendaylight.vpnservice.elan.utils.ElanUtils; +import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo; +import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo.InterfaceType; +import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager; +import org.opendaylight.vpnservice.itm.api.IITMProvider; +import org.opendaylight.vpnservice.itm.globals.ITMConstants; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.ExtensionKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlowBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.grouping.ExtensionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionListBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.reg.grouping.NxmNxRegBuilder; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; +import org.opendaylight.vpnservice.mdsalutil.*; +import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanDpnInterfaces; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanForwardingTables; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanInterfaces; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.forwarding.tables.MacTable; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.forwarding.tables.MacTableKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstanceBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.state.Elan; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.state.ElanBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.state.ElanKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntryBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntryKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigInteger; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + + +public class ElanInterfaceManager extends AbstractDataChangeListener implements AutoCloseable { + + private static ElanInterfaceManager elanInterfaceManager = new ElanInterfaceManager(); + private ListenerRegistration elanInterfaceListenerRegistration; + private ListenerRegistration itmInterfaceListenerRegistration; + private OdlInterfaceRpcService interfaceManagerRpcService; + private DataBroker broker; + private IMdsalApiManager mdsalManager; + private IInterfaceManager interfaceManager; + private IdManagerService idManager; + private IITMProvider itmManager; + private ElanForwardingEntriesHandler elanForwardingEntriesHandler; + private Map> unProcessedElanInterfaces = + new ConcurrentHashMap> (); + + private static final Logger logger = LoggerFactory.getLogger(ElanInterfaceManager.class); + + public ElanInterfaceManager() { + super(ElanInterface.class); + } + + public static ElanInterfaceManager getElanInterfaceManager() { + return elanInterfaceManager; + } + + public void setMdSalApiManager(IMdsalApiManager mdsalManager) { + this.mdsalManager = mdsalManager; + } + + public void setInterfaceManagerRpcService(OdlInterfaceRpcService ifManager) { + this.interfaceManagerRpcService = ifManager; + } + + public void setElanForwardingEntriesHandler(ElanForwardingEntriesHandler elanForwardingEntriesHandler) { + this.elanForwardingEntriesHandler = elanForwardingEntriesHandler; + } + + public void setInterfaceManager(IInterfaceManager interfaceManager) { + this.interfaceManager = interfaceManager; + } + + public void setDataBroker(DataBroker broker) { + this.broker = broker; + } + + public void setIITMManager(IITMProvider itmManager) { + this.itmManager = itmManager; + } + + @Override + public void close() throws Exception { + if (elanInterfaceListenerRegistration != null) { + try { + elanInterfaceListenerRegistration.close(); + } catch (final Exception e) { + logger.error("Error when cleaning up DataChangeListener.", e); + } + elanInterfaceListenerRegistration = null; + } + } + + public void registerListener() { + try { + elanInterfaceListenerRegistration = broker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION, + getElanInterfaceWildcardPath(), ElanInterfaceManager.this, DataChangeScope.SUBTREE); + } catch (final Exception e) { + logger.error("ELAN Interface DataChange listener registration failed !", e); + throw new IllegalStateException("ELAN Interface registration Listener failed.", e); + } + } + + private InstanceIdentifier getElanInterfaceWildcardPath() { + return InstanceIdentifier.create(ElanInterfaces.class).child(ElanInterface.class); + } + + public void setIdManager(IdManagerService idManager) { + this.idManager = idManager; + } + + @Override + protected void remove(InstanceIdentifier identifier, ElanInterface del) { + String interfaceName = del.getName(); + ElanInstance elanInfo = ElanUtils.getElanInstanceByName(del.getElanInstanceName()); + removeElanInterface(elanInfo, interfaceName); + } + + public void removeElanService(ElanInterface del, int vlanId) { + ElanInstance elanInstance = ElanUtils.getElanInstanceByName(del.getElanInstanceName()); + String interfaceName = del.getName(); + InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(interfaceName, InterfaceType.VLAN_INTERFACE); + removeElanInterface(elanInstance, interfaceInfo); + unbindService(elanInstance, interfaceName, vlanId); + } + + public void removeElanInterface(ElanInstance elanInfo, String interfaceName) { + String elanName = elanInfo.getElanInstanceName(); + InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName); + if (interfaceInfo == null) { + ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName); + if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) { + List macEntries = elanInterfaceMac.getMacEntry(); + for(MacEntry macEntry : macEntries) { + ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getMacEntryOperationalDataPath(elanName, macEntry.getMacAddress())); + } + } + ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName)); + Elan elanState = ElanUtils.getElanByName(elanName); + List elanInterfaces = elanState.getElanInterfaces(); + elanInterfaces.remove(interfaceName); + if(elanInterfaces.isEmpty()) { + ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName)); + ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanMacTableOperationalDataPath(elanName)); + ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInfoEntriesOperationalDataPath(elanInfo.getElanTag())); + ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInstanceConfigurationDataPath(elanName)); + } else { + Elan updateElanState = new ElanBuilder().setElanInterfaces(elanInterfaces).setName(elanName).setKey(new ElanKey(elanName)).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName), updateElanState); + } + return; + } + removeElanInterface(elanInfo, interfaceInfo); + unbindService(elanInfo, interfaceName); + } + + private void removeElanInterface(ElanInstance elanInfo, InterfaceInfo interfaceInfo) { + + BigInteger dpId = interfaceInfo.getDpId(); + String elanName = elanInfo.getElanInstanceName(); + String interfaceName = interfaceInfo.getInterfaceName(); + Elan elanState = ElanUtils.getElanByName(elanName); + logger.debug("Removing the Interface:{} from elan:{}", interfaceName, elanName); + InstanceIdentifier elanInterfaceId = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName); + Optional existingElanInterface = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId); + if(existingElanInterface.isPresent()) { + List macEntries = existingElanInterface.get().getMacEntry(); + if(macEntries != null && !macEntries.isEmpty()) { + for (MacEntry macEntry : macEntries) { + logger.debug("removing the mac-entry:{} present on elanInterface:{}", macEntry.getMacAddress().getValue(), interfaceName); + elanForwardingEntriesHandler.deleteElanInterfaceForwardingEntries(elanInfo, interfaceInfo, macEntry); + } + } + } + + /* + *This condition check is mainly to get DPN-ID in pre-provision deletion scenario after stopping CSS + */ + if(dpId.equals(ElanConstants.INVALID_DPN)) { + ElanDpnInterfacesList elanDpnInterfacesList = ElanUtils.getElanDpnInterfacesList(elanName); + if(elanDpnInterfacesList != null && !elanDpnInterfacesList.getDpnInterfaces().isEmpty()) { + List dpnIfList = elanDpnInterfacesList.getDpnInterfaces(); + for (DpnInterfaces dpnInterface : dpnIfList) { + DpnInterfaces dpnIfLists = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpnInterface.getDpId()); + if (dpnIfLists.getInterfaces().contains(interfaceName)) { + logger.debug("deleting the elanInterface from the ElanDpnInterface cache in pre-provision scenario of elan:{} dpn:{} interfaceName:{}", elanName, dpId, interfaceName); + removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId, interfaceName); + break; + } + } + } + } else { + removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId, interfaceName); + } + + ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId); + List elanInterfaces = elanState.getElanInterfaces(); + elanInterfaces.remove(interfaceName); + removeStaticELanFlows(elanInfo, interfaceInfo); + if(elanInterfaces.isEmpty()) { + ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName)); + ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnOperationDataPath(elanName)); + ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanMacTableOperationalDataPath(elanName)); + ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInfoEntriesOperationalDataPath(elanInfo.getElanTag())); + //ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInstanceConfigurationDataPath(elanName)); + } else { + Elan updateElanState = new ElanBuilder().setElanInterfaces(elanInterfaces).setName(elanName).setKey(new ElanKey(elanName)).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName), updateElanState); + } + } + + private void removeElanDpnInterfaceFromOperationalDataStore(String elanName, BigInteger dpId, String interfaceName) { + DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId); + if(dpnInterfaces != null) { + List interfaceLists = dpnInterfaces.getInterfaces(); + interfaceLists.remove(interfaceName); + updateElanDpnInterfacesList(elanName, dpId, interfaceLists); + } + } + + @Override + protected void update(InstanceIdentifier identifier, ElanInterface original, ElanInterface update) { + // updating the static-Mac Entries for the existing elanInterface + String elanName = update.getElanInstanceName(); + String interfaceName = update.getName(); + InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName); + List existingPhysAddress = original.getStaticMacEntries(); + List updatedPhysAddress = update.getStaticMacEntries(); + if(updatedPhysAddress != null && !updatedPhysAddress.isEmpty()) { + List existingClonedPhyAddress = new ArrayList<>(); + if(existingPhysAddress != null && !existingPhysAddress.isEmpty()) { + existingClonedPhyAddress.addAll(0, existingPhysAddress); + existingPhysAddress.removeAll(updatedPhysAddress); + updatedPhysAddress.removeAll(existingClonedPhyAddress); + // removing the PhyAddress which are not presented in the updated List + for(PhysAddress physAddress: existingPhysAddress) { + removeInterfaceStaticMacEntires(elanName, interfaceName, physAddress); + } + } + // Adding the new PhysAddress which are presented in the updated List + if(updatedPhysAddress.size() > 0) { + for(PhysAddress physAddress: updatedPhysAddress) { + InstanceIdentifier macId = getMacEntryOperationalDataPath(elanName, physAddress); + Optional existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macId); + if(existingMacEntry.isPresent()) { + elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList(elanName, interfaceName, existingMacEntry.get().getInterface(), existingMacEntry.get()); + } else { + elanForwardingEntriesHandler.addElanInterfaceForwardingTableList(ElanUtils.getElanInstanceByName(elanName), interfaceName, physAddress); + } + } + } + } else if(existingPhysAddress != null && !existingPhysAddress.isEmpty()) { + for( PhysAddress physAddress : existingPhysAddress) { + removeInterfaceStaticMacEntires(elanName, interfaceName, physAddress); + } + } + } + + @Override + protected void add(InstanceIdentifier identifier, ElanInterface elanInterfaceAdded) { + String elanInstanceName = elanInterfaceAdded.getElanInstanceName(); + String interfaceName = elanInterfaceAdded.getName(); + InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName); + ElanInstance elanInstance = ElanUtils.getElanInstanceByName(elanInstanceName); + + if (elanInstance == null) { + elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName).setDescription(elanInterfaceAdded.getDescription()).build(); + //Add the ElanInstance in the Configuration data-store + ElanUtils.UpdateOperationalDataStore(broker, idManager, elanInstance); + elanInstance = ElanUtils.getElanInstanceByName(elanInstanceName); + } + + + Long elanTag = elanInstance.getElanTag(); + // If elan tag is not updated, then put the elan interface into unprocessed entry map and entry. Let entries + // in this map get processed during ELAN update DCN. + if (elanTag == null) { + ConcurrentLinkedQueue elanInterfaces = unProcessedElanInterfaces.get(elanInstanceName); + if (elanInterfaces == null) { + elanInterfaces = new ConcurrentLinkedQueue(); + } + elanInterfaces.add(elanInterfaceAdded); + unProcessedElanInterfaces.put(elanInstanceName, elanInterfaces); + return; + } + addElanInterface(elanInterfaceAdded, interfaceInfo, elanInstance); + } + + void handleunprocessedElanInterfaces(ElanInstance elanInstance) { + Queue elanInterfaces = unProcessedElanInterfaces.get(elanInstance.getElanInstanceName()); + if (elanInterfaces == null || elanInterfaces.isEmpty()) { + return; + } + for (ElanInterface elanInterface: elanInterfaces) { + String interfaceName = elanInterface.getName(); + InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName); + addElanInterface(elanInterface, interfaceInfo, elanInstance); + } + } + + void addElanInterface(ElanInterface elanInterface, InterfaceInfo interfaceInfo, ElanInstance elanInstance) { + String interfaceName = elanInterface.getName(); + String elanInstanceName = elanInterface.getElanInstanceName(); + List staticMacAddresses = elanInterface.getStaticMacEntries(); + Elan elanInfo = ElanUtils.getElanByName(elanInstanceName); + BigInteger dpId = null; + if(elanInfo == null) { + ElanUtils.UpdateOperationalDataStore(broker, idManager, elanInstance); + } + if(interfaceInfo != null) { + dpId = interfaceInfo.getDpId(); + } + if(dpId != null && !dpId.equals(ElanConstants.INVALID_DPN)) { + InstanceIdentifier elanDpnInterfaces = ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId); + Optional existingElanDpnInterfaces = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfaces); + if (!existingElanDpnInterfaces.isPresent()) { + createElanInterfacesList(elanInstanceName, interfaceName, dpId); + } else { + List elanInterfaces = existingElanDpnInterfaces.get().getInterfaces(); + elanInterfaces.add(interfaceName); + updateElanDpnInterfacesList(elanInstanceName, dpId, elanInterfaces); + } + } + + // add code to install Local/Remote BC group, unknow DMAC entry, terminating service table flow entry + // call bindservice of interfacemanager to create ingress table flow enty. + //Add interface to the ElanInterfaceForwardingEntires Container + createElanInterfaceTablesList(interfaceName); + createElanStateList(elanInstanceName, interfaceName); + if(interfaceInfo != null) { + installFlowsAndGroups(elanInstance, interfaceInfo); + } + // add the static mac addresses + if(staticMacAddresses != null) { + for (PhysAddress physAddress : staticMacAddresses) { + InstanceIdentifier macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress); + Optional existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macId); + if (existingMacEntry.isPresent()) { + elanForwardingEntriesHandler.updateElanInterfaceForwardingTablesList(elanInstanceName, interfaceName, existingMacEntry.get().getInterface(), existingMacEntry.get()); + } else { + elanForwardingEntriesHandler.addElanInterfaceForwardingTableList(elanInstance, interfaceName, physAddress); + } + if(interfaceInfo != null && isOperational(interfaceInfo)) { + logger.debug("Installing Static Mac-Entry on the Elan Interface:{} with MacAddress:{}", interfaceInfo, physAddress.getValue()); + ElanUtils.setupMacFlows(elanInstance, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT, physAddress.getValue()); + } + } + } + } + + private Map> readFePortsDbForElan(String elanName) { + ElanDpnInterfacesList elanDpnInterfacesList = ElanUtils.getElanDpnInterfacesList(elanName); + HashMap> fePortsDb = Maps.newHashMap(); + if (elanDpnInterfacesList == null) { + return fePortsDb; + } + List dpnInterfaces = elanDpnInterfacesList.getDpnInterfaces(); + if (dpnInterfaces == null) { + return fePortsDb; + } + for (DpnInterfaces dpnInterface : dpnInterfaces) { + fePortsDb.put(dpnInterface.getDpId(), dpnInterface.getInterfaces()); + } + return fePortsDb; + } + + protected void removeInterfaceStaticMacEntires(String elanInstanceName, String interfaceName, PhysAddress physAddress) { + InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName); + InstanceIdentifier macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress); + Optional existingMacEntry = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, macId); + + if(!existingMacEntry.isPresent()) { + return; + } + + MacEntry macEntry = new MacEntryBuilder().setMacAddress(physAddress).setInterface(interfaceName).setKey(new MacEntryKey(physAddress)).build(); + elanForwardingEntriesHandler.deleteElanInterfaceForwardingEntries(ElanUtils.getElanInstanceByName(elanInstanceName), interfaceInfo, macEntry); + elanForwardingEntriesHandler.deleteElanInterfaceMacForwardingEntries(interfaceName, physAddress); + } + + + private InstanceIdentifier getMacEntryOperationalDataPath(String elanName, PhysAddress physAddress) { + return InstanceIdentifier.builder(ElanForwardingTables.class).child(MacTable.class, + new MacTableKey(elanName)).child(MacEntry.class, new MacEntryKey(physAddress)).build(); + } + + public void installFlowsAndGroups(final ElanInstance elanInfo, final InterfaceInfo interfaceInfo) { + if (isOperational(interfaceInfo)) { + + // LocalBroadcast Group creation with elan-Interfaces + setupLocalBroadcastGroups(elanInfo, interfaceInfo); + + //Remote-broadcast group & Terminating Service , UnknownDMAC Table. + //setupRemoteBroadcastGroups(elanInfo, interfaceInfo); + setupTerminateServiceTable(elanInfo, interfaceInfo); + setupUnknownDMacTable(elanInfo, interfaceInfo); + setupFilterEqualsTable(elanInfo, interfaceInfo); + // bind the Elan service to the Interface + bindService(elanInfo, interfaceInfo.getInterfaceName()); + + //update the remote-DPNs remoteBC group entry with Tunnels + setRemoteBCGrouponOtherDpns(elanInfo, interfaceInfo); + } + } + + public void setupFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) { + long elanTag = elanInfo.getElanTag(); + long ifTag = interfaceInfo.getInterfaceTag(); + List mkMatches = new ArrayList(); + MatchBuilder mb = new MatchBuilder(); + addNxRegMatch(mb, RegMatch.of(NxmNxReg1.class, ifTag)); + FlowEntity flowEntity = MDSALUtil.buildFlowEntity(interfaceInfo.getDpId(), ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, ifTag), + 9, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getMatchesForFilterEqualsReg1LPortTag(ifTag), + getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName())); + + mdsalManager.installFlow(flowEntity); + + FlowEntity flowEntity1 = MDSALUtil.buildFlowEntity(interfaceInfo.getDpId(), ElanConstants.ELAN_FILTER_EQUALS_TABLE, getFlowRef(ElanConstants.ELAN_FILTER_EQUALS_TABLE, 1000+ifTag), + 10, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)), getMatchesForFilterEqualsLPortTag(ifTag), + getInstructionsDrop()); + + mdsalManager.installFlow(flowEntity1); + } + + + protected List getEgressActionsForInterface(String ifName) { + List listActionInfo = new ArrayList(); + try { + Future> result = + interfaceManagerRpcService.getEgressActionsForInterface( + new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName).build()); + RpcResult rpcResult = result.get(); + System.out.println("Data is populated"); + if(!rpcResult.isSuccessful()) { + logger.warn("RPC Call to Get egress actions for interface {} returned with Errors {}", ifName, rpcResult.getErrors()); + } else { + List actions = + rpcResult.getResult().getAction(); + for (Action action : actions) { + org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action actionClass = action.getAction(); + if (actionClass instanceof OutputActionCase) { + System.out.println("Data "); + listActionInfo.add(new ActionInfo(ActionType.output, + new String[] {((OutputActionCase)actionClass).getOutputAction() + .getOutputNodeConnector().getValue()})); + } else if (actionClass instanceof PushVlanActionCase) { + listActionInfo.add(new ActionInfo(ActionType.push_vlan, new String[] {})); + } else if (actionClass instanceof SetFieldCase) { + if (((SetFieldCase)actionClass).getSetField().getVlanMatch() != null) { + int vlanVid = ((SetFieldCase)actionClass).getSetField().getVlanMatch().getVlanId().getVlanId().getValue(); + listActionInfo.add(new ActionInfo(ActionType.set_field_vlan_vid, + new String[] { Long.toString(vlanVid) })); + } + } + } + } + } catch (InterruptedException | ExecutionException e) { + logger.warn("Exception when egress actions for interface {}", ifName, e); + } + return listActionInfo; + } + + + private List getRemoteBCGroupBucketInfos(ElanInstance elanInfo, + InterfaceInfo interfaceInfo) { + BigInteger dpnId = interfaceInfo.getDpId(); + int elanTag = elanInfo.getElanTag().intValue(); + List listBucketInfo = new ArrayList(); + ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName()); + if(elanDpns != null) { + List dpnInterfaceses = elanDpns.getDpnInterfaces(); + for(DpnInterfaces dpnInterface : dpnInterfaceses) { + if(ElanUtils.isDpnPresent(dpnInterface.getDpId()) && dpnInterface.getDpId() != dpnId && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) { + try { + //FIXME [ELANBE] Removing ITM API for now, will need this for multi dpn. + //List listActionInfo = itmManager.ITMIngressGetActions(dpnId, dpnInterface.getDpId(), (int) elanTag); + //listBucketInfo.add(new BucketInfo(listActionInfo)); + } catch (Exception ex) { + logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnId, dpnInterface.getDpId() ); + } + } + } + } + List listActionInfo = new ArrayList(); + listActionInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(ElanUtils.getElanLocalBCGID(elanInfo.getElanTag()))})); + listBucketInfo.add(new BucketInfo(listActionInfo)); + return listBucketInfo; + } + + public ActionInfo getReg1ActionInfo(int interfaceTag) { + return new ActionInfo(ActionType.set_field_reg, new String[] {String.valueOf(interfaceTag)}); + } + + private void setRemoteBCGrouponOtherDpns(ElanInstance elanInfo, + InterfaceInfo interfaceInfo) { + BigInteger dpnId = interfaceInfo.getDpId(); + int elanTag = elanInfo.getElanTag().intValue(); + long groupId = ElanUtils.getElanRemoteBCGID(elanTag); + ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName()); + if(elanDpns != null) { + List dpnInterfaceses = elanDpns.getDpnInterfaces(); + for(DpnInterfaces dpnInterface : dpnInterfaceses) { + List remoteListBucketInfo = new ArrayList(); + if(ElanUtils.isDpnPresent(dpnInterface.getDpId()) && !dpnInterface.getDpId().equals(dpnId) && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) { + for(DpnInterfaces otherFes : dpnInterfaceses) { + if (ElanUtils.isDpnPresent(otherFes.getDpId()) && otherFes.getDpId() != dpnInterface.getDpId() + && otherFes.getInterfaces() != null && ! otherFes.getInterfaces().isEmpty()) { + try { + //FIXME [ELANBE] Removing ITM API for now, will need this for multi dpn. + //List remoteListActionInfo = itmManager.ITMIngressGetActions(dpnInterface.getDpId(), otherFes.getDpId(), (int) elanTag); + //remoteListBucketInfo.add(new BucketInfo(remoteListActionInfo)); + } catch (Exception ex) { + logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnInterface.getDpId(), otherFes.getDpId() ); + return; + } + } + } + List remoteListActionInfo = new ArrayList(); + remoteListActionInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(ElanUtils.getElanLocalBCGID(elanTag))})); + remoteListBucketInfo.add(new BucketInfo(remoteListActionInfo)); + GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnInterface.getDpId(), groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, remoteListBucketInfo); + mdsalManager.installGroup(groupEntity); + } + } + } + } + + private void updateRemoteBCGrouponDpnTunnelEvent(ElanInstance elanInfo, + InterfaceInfo interfaceInfo, BigInteger dstDpId) { + int elanTag = elanInfo.getElanTag().intValue(); + long groupId = ElanUtils.getElanRemoteBCGID(elanTag); + List elanDpns = ElanUtils.getInvolvedDpnsInElan(elanInfo.getElanInstanceName()); + if(elanDpns != null) { + for(DpnInterfaces dpnInterface : elanDpns) { + List remoteListBucketInfo = new ArrayList(); + if(ElanUtils.isDpnPresent(dstDpId) && dpnInterface.getDpId().equals(dstDpId) && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) { + try { + //FIXME [ELANBE] Removing ITM API for now, will need this for multi dpn. + //List remoteListActionInfo = itmManager.ITMIngressGetActions(interfaceInfo.getDpId(), dstDpId, (int) elanTag); + //remoteListBucketInfo.add(new BucketInfo(remoteListActionInfo)); + } catch (Exception ex) { + logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnInterface.getDpId(), dstDpId); + return; + } + List remoteListActionInfo = new ArrayList(); + remoteListActionInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(ElanUtils.getElanLocalBCGID(elanTag))})); + remoteListBucketInfo.add(new BucketInfo(remoteListActionInfo)); + GroupEntity groupEntity = MDSALUtil.buildGroupEntity(interfaceInfo.getDpId(), groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, remoteListBucketInfo); + mdsalManager.installGroup(groupEntity); + break; + } + } + } + } + + + /** + * Returns the bucket info with the given interface as the only bucket. + */ + private List getLocalBCGroupBucketInfo(InterfaceInfo interfaceInfo) { + return Lists.newArrayList(new BucketInfo(getInterfacePortActionInfos(interfaceInfo))); + } + + private List getMatchesForElanTag(Long elanTag) { + List mkMatches = new ArrayList(); + // Matching metadata + mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] { + ElanUtils.getElanMetadataLabel(elanTag), + MetaDataUtil.METADATA_MASK_SERVICE })); + return mkMatches; + } + + private List getInstructionsForOutGroup( + long groupId) { + List mkInstructions = new ArrayList(); + List actionsInfos = new ArrayList (); + actionsInfos.add(new ActionInfo(ActionType.group, new String[]{Long.toString(groupId)})); + mkInstructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos)); + return mkInstructions; + } + + public void removeFlowsAndGroups(ElanInstance elanInfo, InterfaceInfo interfaceInfo) { + removeStaticELanFlows(elanInfo, interfaceInfo); + unbindService(elanInfo, interfaceInfo.getInterfaceName()); + } + + public void installMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo) { + String interfaceName = interfaceInfo.getInterfaceName(); + BigInteger currentDpn = interfaceInfo.getDpId(); + ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName); + if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) { + List macEntries = elanInterfaceMac.getMacEntry(); + for(MacEntry macEntry : macEntries) { + PhysAddress physAddress = macEntry.getMacAddress(); + ElanUtils.setupMacFlows(elanInfo, interfaceInfo, macEntry.isIsStaticAddress() ? ElanConstants.STATIC_MAC_TIMEOUT : elanInfo.getMacTimeout(), physAddress.getValue()); + } + //Programming the remoteDMACFlows + ElanDpnInterfacesList elanDpnInterfacesList = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName()); + List dpnInterfaceLists = elanDpnInterfacesList.getDpnInterfaces(); + for(DpnInterfaces dpnInterfaces : dpnInterfaceLists){ + if(dpnInterfaces.getDpId().equals(interfaceInfo.getDpId())) { + continue; + } + List remoteElanInterfaces = dpnInterfaces.getInterfaces(); + for(String remoteIf : remoteElanInterfaces) { + ElanInterfaceMac elanIfMac = ElanUtils.getElanInterfaceMacByInterfaceName(remoteIf); + InterfaceInfo remoteInterface = interfaceManager.getInterfaceInfo(remoteIf); + if(elanIfMac == null) { + continue; + } + List remoteMacEntries = elanIfMac.getMacEntry(); + if(remoteMacEntries != null) { + for (MacEntry macEntry : remoteMacEntries) { + PhysAddress physAddress = macEntry.getMacAddress(); + ElanUtils.setupRemoteDmacFlow(currentDpn, remoteInterface.getDpId(), remoteInterface.getInterfaceTag(), elanInfo.getElanTag(), physAddress.getValue(), elanInfo.getElanInstanceName()); + } + } + } + } + } + } + + // Install DMAC entry on dst DPN + public void installDMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo, BigInteger dstDpId) { + String interfaceName = interfaceInfo.getInterfaceName(); + ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName); + if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) { + List macEntries = elanInterfaceMac.getMacEntry(); + for(MacEntry macEntry : macEntries) { + PhysAddress physAddress = macEntry.getMacAddress(); + ElanUtils.setupDMacFlowonRemoteDpn(elanInfo, interfaceInfo, dstDpId, physAddress.getValue()); + } + } + } + + public void removeMacAddressTables(ElanInstance elanInfo, InterfaceInfo interfaceInfo) { + ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceInfo.getInterfaceName()); + if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) { + List macEntries = elanInterfaceMac.getMacEntry(); + for(MacEntry macEntry : macEntries) { + ElanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry); + } + } + } + + public void setupLocalBroadcastGroups(ElanInstance elanInfo, InterfaceInfo interfaceInfo) { + List listBucketInfo = new ArrayList(); + BigInteger dpnId = interfaceInfo.getDpId(); + long groupId = ElanUtils.getElanLocalBCGID(elanInfo.getElanTag()); + + DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanInfo.getElanInstanceName(), dpnId); + for(String ifName : dpnInterfaces.getInterfaces()) { + // In case if there is a InterfacePort in the cache which is not in + // operational state, skip processing it + InterfaceInfo ifInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(ifName, interfaceInfo.getInterfaceType()); + if (!isOperational(ifInfo)) { + continue; + } + + listBucketInfo.add(new BucketInfo(getInterfacePortActionInfos(ifInfo))); + } + GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, listBucketInfo); + logger.trace("installing the localBroadCast GroupEntity:{}", groupEntity); + mdsalManager.syncInstallGroup(groupEntity, ElanConstants.DELAY_TIME_IN_MILLISECOND); + } + + public void removeLocalBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo) { + BigInteger dpnId = interfaceInfo.getDpId(); + long groupId = ElanUtils.getElanLocalBCGID(elanInfo.getElanTag()); + + GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, getLocalBCGroupBucketInfo(interfaceInfo)); + logger.trace("deleted the localBroadCast GroupEntity:{}", groupEntity); + mdsalManager.syncRemoveGroup(groupEntity); + } + + public void setupRemoteBroadcastGroups(ElanInstance elanInfo, InterfaceInfo interfaceInfo) { + List listBucketInfo = getRemoteBCGroupBucketInfos(elanInfo, interfaceInfo); + BigInteger dpnId = interfaceInfo.getDpId(); + long groupId = ElanUtils.getElanRemoteBCGID(elanInfo.getElanTag()); + GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, listBucketInfo); + mdsalManager.syncInstallGroup(groupEntity, ElanConstants.DELAY_TIME_IN_MILLISECOND); + } + + public void removeRemoteBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo) { + List listBucketInfo = getRemoteBCGroupBucketInfos(elanInfo, interfaceInfo); + BigInteger dpnId = interfaceInfo.getDpId(); + long groupId = ElanUtils.getElanRemoteBCGID(elanInfo.getElanTag()); + GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, listBucketInfo); + logger.trace("deleting the remoteBroadCast GroupEntity:{}", groupEntity); + mdsalManager.syncRemoveGroup(groupEntity); + } + + public void setupTerminateServiceTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) { + long elanTag = elanInfo.getElanTag(); + //FIXME [ELANBE] Removing ITM API for now, will need this for multi dpn. +// FlowEntity flowEntity = MDSALUtil.buildFlowEntity(interfaceInfo.getDpId(), ITMConstants.TERMINATING_SERVICE_TABLE, getFlowRef(ITMConstants.TERMINATING_SERVICE_TABLE, elanTag), +// 5, elanInfo.getElanInstanceName(), 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(elanTag)), itmManager.getTunnelMatchesForServiceId(elanTag), +// getInstructionsForOutGroup(ElanUtils.getElanLocalBCGID(elanTag))); +// +// mdsalManager.installFlow(flowEntity); + } + + public void setupUnknownDMacTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) { + long elanTag = elanInfo.getElanTag(); + FlowEntity flowEntity = MDSALUtil.buildFlowEntity(interfaceInfo.getDpId(), ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, getFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag), + 5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)), getMatchesForElanTag(elanTag), + getInstructionsForOutGroup(ElanUtils.getElanLocalBCGID(elanTag))); + + mdsalManager.installFlow(flowEntity); + } + + private void removeStaticELanFlows(final ElanInstance elanInfo, final InterfaceInfo interfaceInfo) { + BigInteger dpId = interfaceInfo.getDpId(); + long elanTag = elanInfo.getElanTag(); + /* + * If there are not elan ports, remove the unknown smac and default dmac + * flows + */ + DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanInfo.getElanInstanceName(), dpId); + if(dpnInterfaces == null) { + return; + } + List elanInterfaces = dpnInterfaces.getInterfaces(); + if (elanInterfaces == null || elanInterfaces.isEmpty()) { + + logger.debug("deleting the elan: {} present on dpId: {}", elanInfo.getElanInstanceName(), dpId); + removeDefaultTermFlow(dpId, elanInfo.getElanTag()); + removeUnknownDmacFlow(dpId, elanInfo); + removeRemoteBroadcastGroup(elanInfo, interfaceInfo); + removeLocalBroadcastGroup(elanInfo, interfaceInfo); + } else { + setupLocalBroadcastGroups(elanInfo, interfaceInfo); + } + } + + private void removeUnknownDmacFlow(BigInteger dpId, ElanInstance elanInfo) { + FlowEntity flowEntity = getUnknownDmacFlowEntity(dpId, elanInfo); + mdsalManager.syncRemoveFlow(flowEntity, ElanConstants.DELAY_TIME_IN_MILLISECOND); + } + + private void removeDefaultTermFlow(BigInteger dpId, long elanTag) { + //FIXME [ELANBE] Removing ITM API for now, will need this for multi dpn. + //itmManager.removeTerminatingServiceAction(dpId, (int) elanTag); + } + + private void bindService(ElanInstance elanInfo, String interfaceName) { + // interfaceManager.bindService(interfaceName, ElanUtils.getServiceInfo(elanInfo.getElanInstanceName(), elanInfo.getElanTag(), interfaceName)); + + int priority = ElanConstants.ELAN_SERVICE_PRIORITY; + int instructionKey = 0; + List instructions = new ArrayList(); + instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(ElanUtils.getElanMetadataLabel(elanInfo.getElanTag()), MetaDataUtil.METADATA_MASK_SERVICE, ++instructionKey)); + instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(ElanConstants.ELAN_SMAC_TABLE, ++instructionKey)); + BoundServices + serviceInfo = + ElanUtils.getBoundServices(String.format("%s.%s.%s", "vpn",elanInfo.getElanInstanceName(), interfaceName), + ElanConstants.ELAN_SERVICE_INDEX, priority, + ElanConstants.COOKIE_ELAN_INGRESS_TABLE, instructions); + ElanUtils.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, + ElanUtils.buildServiceId(interfaceName, ElanConstants.ELAN_SERVICE_INDEX), serviceInfo); + } + + private void unbindService(ElanInstance elanInfo, String interfaceName) { + ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION, + ElanUtils.buildServiceId(interfaceName,ElanConstants.ELAN_SERVICE_INDEX), + ElanUtils.DEFAULT_CALLBACK); + } + + private void unbindService(ElanInstance elanInfo, String interfaceName, int vlanId) { + ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION, + ElanUtils.buildServiceId(interfaceName,ElanConstants.ELAN_SERVICE_INDEX), + ElanUtils.DEFAULT_CALLBACK); + } + + private FlowEntity getUnknownDmacFlowEntity(BigInteger dpId, ElanInstance elanInfo) { + long elanTag = elanInfo.getElanTag(); + List mkMatches = new ArrayList(); + // Matching metadata + mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] { + ElanUtils.getElanMetadataLabel(elanTag), + MetaDataUtil.METADATA_MASK_SERVICE })); + + List mkInstructions = new ArrayList(); + List actionsInfos = new ArrayList (); + actionsInfos.add(new ActionInfo(ActionType.group, new String[]{Long.toString(ElanUtils.getElanRemoteBCGID(elanTag))})); + mkInstructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos)); + + FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, getFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag), + 5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)), + mkMatches, mkInstructions); + return flowEntity; + } + + private String getFlowRef(long tableId, long elanTag) { + return new StringBuffer().append(tableId).append(elanTag).toString(); + } + + private List getInterfacePortActionInfos(InterfaceInfo interfaceInfo) { + List listActionInfo = new ArrayList(); + listActionInfo.add(getReg1ActionInfo(interfaceInfo.getInterfaceTag())); + listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[]{})); + return listActionInfo; + } + + private void updateElanDpnInterfacesList(String elanInstanceName, BigInteger dpId, List interfaceNames) { + if(!interfaceNames.isEmpty()) { + DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId) + .setInterfaces(interfaceNames).setKey(new DpnInterfacesKey(dpId)).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId), + dpnInterface); + } else { + MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId)); + } + + } + + private List createElanInterfacesList(String elanInstanceName, String interfaceName, BigInteger dpId) { + List interfaceNames = new ArrayList(); + interfaceNames.add(interfaceName); + DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId) + .setInterfaces(interfaceNames).setKey(new DpnInterfacesKey(dpId)).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId), + dpnInterface); + return interfaceNames; + } + + private void createElanInterfaceTablesList(String interfaceName) { + InstanceIdentifier elanInterfaceMacTables = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName); + Optional interfaceMacTables = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceMacTables); + // Adding new Elan Interface Port to the operational DataStore without Static-Mac Entries.. + if(!interfaceMacTables.isPresent()) { + ElanInterfaceMac elanInterfaceMacTable = new ElanInterfaceMacBuilder().setElanInterface(interfaceName).setKey(new ElanInterfaceMacKey(interfaceName)).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName), + elanInterfaceMacTable); + } + } + + private void createElanStateList(String elanInstanceName, String interfaceName) { + InstanceIdentifier elanInstance = ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName); + Optional elanInterfaceLists = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInstance); + // Adding new Elan Interface Port to the operational DataStore without Static-Mac Entries.. + if(elanInterfaceLists.isPresent()) { + List interfaceLists = elanInterfaceLists.get().getElanInterfaces(); + if(interfaceLists == null) { + interfaceLists = new ArrayList<>(); + } + interfaceLists.add(interfaceName); + Elan elanState = new ElanBuilder().setName(elanInstanceName).setElanInterfaces(interfaceLists).setKey(new ElanKey(elanInstanceName)).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName), elanState); + } + } + + private boolean isOperational(InterfaceInfo interfaceInfo) { + return ((interfaceInfo.getOpState() == InterfaceInfo.InterfaceOpState.UP) && (interfaceInfo.getAdminState() == InterfaceInfo.InterfaceAdminState.ENABLED)); + } + + protected void updatedIfPrimaryAttributeChanged(ElanInterface elanInterface, boolean isUpdated) { + String interfaceName = elanInterface.getName(); + InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName); + BigInteger dpId = interfaceInfo.getDpId(); + InstanceIdentifier elanInterfaceId = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName); + Optional existingElanInterface = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId); + ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanInterface.getElanInstanceName()); + + if(!existingElanInterface.isPresent()) { + return; + } + + List macEntries = existingElanInterface.get().getMacEntry(); + if(macEntries != null && !macEntries.isEmpty()) { + for (MacEntry macEntry : macEntries) { + if(isUpdated) { + ElanUtils.setupMacFlows(elanInfo, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT, macEntry.getMacAddress().getValue()); + } else { + ElanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry); + } + } + } + + InstanceIdentifier dpnInterfaceId = ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInterface.getElanInstanceName(), interfaceInfo.getDpId()); + Optional dpnInterfaces = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, dpnInterfaceId); + List interfaceLists = dpnInterfaces.get().getInterfaces(); + + if(isUpdated) { + interfaceLists.add(elanInterface.getName()); + } else { + interfaceLists.remove(elanInterface.getName()); + } + + DpnInterfaces updateDpnInterfaces = new DpnInterfacesBuilder().setInterfaces(interfaceLists).setDpId(dpId).setKey(new DpnInterfacesKey(dpId)).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, dpnInterfaceId, updateDpnInterfaces); + + if(isUpdated) { + installFlowsAndGroups(elanInfo, interfaceInfo); + } else { + removeStaticELanFlows(elanInfo, interfaceInfo); + unbindService(elanInfo, interfaceName); + } + } + + public void handleTunnelStateEvent(BigInteger srcDpId, BigInteger dstDpId) { + ElanDpnInterfaces dpnInterfaceLists = ElanUtils.getElanDpnInterfacesList(); + Set elanInstancesMap = new HashSet<>(); + if(dpnInterfaceLists == null) { + return; + } + List elanDpnIf = dpnInterfaceLists.getElanDpnInterfacesList(); + for(ElanDpnInterfacesList elanDpns: elanDpnIf) { + int cnt = 0; + String elanName = elanDpns.getElanInstanceName(); + List dpnInterfaces = elanDpns.getDpnInterfaces(); + if(dpnInterfaces == null) { + continue; + } + for (DpnInterfaces dpnIf : dpnInterfaces) { + if(dpnIf.getDpId().equals(srcDpId) || dpnIf.getDpId().equals(dstDpId)) { + cnt++; + } + } + if(cnt == 2) { + logger.debug("Elan instance:{} is present b/w srcDpn:{} and dstDpn:{}", elanName, srcDpId, dstDpId); + DpnInterfaces dpnInterface = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, srcDpId); + Set interfaceLists = new HashSet<>(); + ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanName); + interfaceLists.addAll(dpnInterface.getInterfaces()); + for(String ifName : interfaceLists) { + InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(ifName); + if (isOperational(interfaceInfo)) { + if (interfaceInfo.getDpId().equals(srcDpId) && !elanInstancesMap.contains(elanDpns.getElanInstanceName())) { + elanInstancesMap.add(elanDpns.getElanInstanceName()); + elanInterfaceManager.updateRemoteBCGrouponDpnTunnelEvent(elanInfo, interfaceInfo, dstDpId); + } + elanInterfaceManager.installDMacAddressTables(elanInfo, interfaceInfo, dstDpId); + } + } + } + + } + } + + public void handleInterfaceUpated(InterfaceInfo interfaceInfo, ElanInstance elanInstance, boolean isStateUp) { + BigInteger dpId = interfaceInfo.getDpId(); + String elanName = elanInstance.getElanInstanceName(); + String ifName = interfaceInfo.getInterfaceName(); + logger.trace("Handling interface update event for interface with info {} , state {}", interfaceInfo, isStateUp); + if(isStateUp) { + + DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId); + if(dpnInterfaces == null) { + createElanInterfacesList(elanName, interfaceInfo.getInterfaceName(), dpId); + } else { + List dpnElanInterfaces = dpnInterfaces.getInterfaces(); + dpnElanInterfaces.add(interfaceInfo.getInterfaceName()); + DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId) + .setInterfaces(dpnElanInterfaces).setKey(new DpnInterfacesKey(dpId)).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanName, interfaceInfo.getDpId()), dpnInterface); + } + + logger.trace("ElanInterface Service is installed for interface:{}", ifName); + elanInterfaceManager.installFlowsAndGroups(elanInstance, interfaceInfo); + elanInterfaceManager.installMacAddressTables(elanInstance, interfaceInfo); + } else { + + DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId); + if(dpnInterfaces != null) { + List dpnElanInterfaces = dpnInterfaces.getInterfaces(); + dpnElanInterfaces.remove(interfaceInfo.getInterfaceName()); + DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId) + .setInterfaces(dpnElanInterfaces).setKey(new DpnInterfacesKey(dpId)).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanName, interfaceInfo.getDpId()), dpnInterface); + } + logger.trace("ElanInterface Service is removed for the interface:{}", ifName); + elanInterfaceManager.removeMacAddressTables(elanInstance, interfaceInfo); + elanInterfaceManager.removeFlowsAndGroups(elanInstance, interfaceInfo); + } + } + + private List getMatchesForFilterEqualsLPortTag(Long LportTag) { + List mkMatches = new ArrayList(); + // Matching metadata + mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] { + ElanUtils.getElanMetadataLabel(LportTag), + MetaDataUtil.METADATA_MASK_SERVICE })); + mkMatches.add(new MatchInfo(MatchFieldType.reg1, new long[] {LportTag.longValue()})); + return mkMatches; + } + + + private List getMatchesForFilterEqualsReg1LPortTag(Long LportTag) { + List mkMatches = new ArrayList(); + // Matching metadata + mkMatches.add(new MatchInfo(MatchFieldType.reg1, new long[] { + (LportTag.longValue())})); + return mkMatches; + + + } + + public static class RegMatch { + + final Class reg; + final Long value; + + public RegMatch(Class reg, Long value) { + super(); + this.reg = reg; + this.value = value; + } + + public static RegMatch of(Class reg, Long value) { + return new RegMatch(reg, value); + } + } + + public static void addNxRegMatch(MatchBuilder match, RegMatch... matches) { + ArrayList extensions = new ArrayList<>(); + for (RegMatch rm : matches) { + Class key; + if (NxmNxReg0.class.equals(rm.reg)) { + key = NxmNxReg0Key.class; + } else if (NxmNxReg1.class.equals(rm.reg)) { + key = NxmNxReg1Key.class; + } else if (NxmNxReg2.class.equals(rm.reg)) { + key = NxmNxReg2Key.class; + } else if (NxmNxReg3.class.equals(rm.reg)) { + key = NxmNxReg3Key.class; + } else if (NxmNxReg4.class.equals(rm.reg)) { + key = NxmNxReg4Key.class; + } else if (NxmNxReg5.class.equals(rm.reg)) { + key = NxmNxReg5Key.class; + } else if (NxmNxReg6.class.equals(rm.reg)) { + key = NxmNxReg6Key.class; + } else { + key = NxmNxReg7Key.class; + } + NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxReg( + new NxmNxRegBuilder().setReg(rm.reg).setValue(rm.value).build()).build(); + extensions.add(new ExtensionListBuilder().setExtensionKey(key) + .setExtension(new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build()) + .build()); + } + GeneralAugMatchNodesNodeTableFlow m = new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList( + extensions).build(); + match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m); + + } + + + private List getInstructionsInPortForOutGroup( + long GroupId) { + List mkInstructions = new ArrayList(); + List actionsInfos = new ArrayList (); + actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[]{ "123"})); + actionsInfos.add(new ActionInfo(ActionType.group, new String[]{Long.toString(GroupId)})); + mkInstructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos)); + return mkInstructions; + } + + private List getInstructionsInPortForOutGroup( + String ifName) { + List mkInstructions = new ArrayList(); + List actionsInfos = new ArrayList (); + //TODO: modify in-port action + //actionsInfos.add(new ActionInfo(ActionType.set_source_port_field, new String[]{ "255"})); + actionsInfos.addAll(getEgressActionsForInterface(ifName)); + mkInstructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos)); + return mkInstructions; + } + + + + private List getInstructionsDrop() { + List mkInstructions = new ArrayList(); + List actionsInfos = new ArrayList (); + actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[]{})); + mkInstructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos)); + return mkInstructions; + } + +} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanItmEventListener.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanItmEventListener.java new file mode 100755 index 00000000..2f8394cd --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanItmEventListener.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.internal; + +//import org.opendaylight.controller.md.sal.binding.api.DataBroker; +//import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +//import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker; +//import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +//import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.TunnelsState; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.tunnels_state.StateTunnelList; +//import org.opendaylight.yangtools.concepts.ListenerRegistration; +//import org.opendaylight.yangtools.yang.binding.DataObject; +//import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +//import org.slf4j.Logger; +//import org.slf4j.LoggerFactory; +// +//import java.math.BigInteger; + +public class ElanItmEventListener{ + +} +//public class ElanItmEventListener extends AbstractDataChangeListener implements AutoCloseable { +//FIXME: This class is to be made functional once ITM is added +// private static final Logger logger = LoggerFactory.getLogger(ElanItmEventListener.class); +// private final DataBroker broker; +// private ListenerRegistration listenerRegistration; +// private ElanInterfaceManager elanInterfaceManager; +// +// public ElanItmEventListener(final DataBroker db, final ElanInterfaceManager ifManager) { +// super(StateTunnelList.class); +// broker = db; +// elanInterfaceManager = ifManager; +// registerListener(db); +// } +// +// private void registerListener(final DataBroker db) { +// try { +// listenerRegistration = broker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, +// getWildCardPath(), ElanItmEventListener.this, AsyncDataBroker.DataChangeScope.SUBTREE); +// } catch (final Exception e) { +// logger.error("ITM Monitor Interfaces DataChange listener registration fail!", e); +// throw new IllegalStateException("ITM Monitor registration Listener failed.", e); +// } +// } +// +// private InstanceIdentifier getWildCardPath() { +// return InstanceIdentifier.create(TunnelsState.class).child(StateTunnelList.class); +// } +// +// @Override +// public void close() throws Exception { +// if (listenerRegistration != null) { +// try { +// listenerRegistration.close(); +// } catch (final Exception e) { +// logger.error("Error when cleaning up DataChangeListener.", e); +// } +// listenerRegistration = null; +// } +// } +// +// @Override +// protected void remove(InstanceIdentifier identifier, StateTunnelList del) { +// +// } +// +// @Override +// protected void update(InstanceIdentifier identifier, StateTunnelList original, StateTunnelList update) { +// BigInteger srcDpId = update.getSourceDPN(); +// BigInteger dstDpId = update.getDestinationDPN(); +// logger.trace("ITM Tunnel state event changed from :{} to :{} for transportZone:{}",original.isLogicalTunnelState(), update.isLogicalTunnelState(), update.getLogicalTunnelGroupName()); +// +// if(update.isLogicalTunnelState()) { +// logger.trace("ITM Tunnel State is Up b/w srcDpn: {} and dstDpn: {}", srcDpId, dstDpId); +// elanInterfaceManager.handleTunnelStateEvent(srcDpId, dstDpId); +// } +// } +// +// @Override +// protected void add(InstanceIdentifier identifier, StateTunnelList add) { +// BigInteger srcDpId = add.getSourceDPN(); +// BigInteger dstDpId = add.getDestinationDPN(); +// logger.trace("ITM Tunnel state event:{} for transportZone:{} of {}", add.isLogicalTunnelState(), add.getLogicalTunnelGroupName()); +// +// if(add.isLogicalTunnelState()) { +// logger.trace("ITM Tunnel State is Up b/w srcDpn: {} and dstDpn: {}", srcDpId, dstDpId); +// elanInterfaceManager.handleTunnelStateEvent(srcDpId, dstDpId); +// } +// } +//} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanNodeListener.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanNodeListener.java new file mode 100644 index 00000000..05a808ce --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanNodeListener.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.internal; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; +import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener; +import org.opendaylight.vpnservice.elan.utils.ElanConstants; +import org.opendaylight.vpnservice.mdsalutil.*; +import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + +public class ElanNodeListener extends AbstractDataChangeListener { + + private static final Logger logger = LoggerFactory.getLogger(ElanNodeListener.class); + + private IMdsalApiManager mdsalManager; + private ListenerRegistration listenerRegistration; + private final DataBroker broker; + + public ElanNodeListener(final DataBroker db, IMdsalApiManager mdsalManager) { + super(Node.class); + broker = db; + this.mdsalManager = mdsalManager; + registerListener(db); + } + + private void registerListener(final DataBroker db) { + try { + listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, + getWildCardPath(), ElanNodeListener.this, AsyncDataBroker.DataChangeScope.SUBTREE); + } catch (final Exception e) { + logger.error("IfmNodeConnectorListener: DataChange listener registration fail!", e); + throw new IllegalStateException("IfmNodeConnectorListener: registration Listener failed.", e); + } + } + + private InstanceIdentifier getWildCardPath() { + return InstanceIdentifier.create(Nodes.class).child(Node.class); + } + + + @Override + protected void remove(InstanceIdentifier identifier, Node del) { + + } + + @Override + protected void update(InstanceIdentifier identifier, Node original, Node update) { + + } + + @Override + protected void add(InstanceIdentifier identifier, Node add) { + NodeId nodeId = add.getId(); + String[] node = nodeId.getValue().split(":"); + BigInteger dpId = new BigInteger(node[1]); + createTableMissEntry(dpId); + } + + public void createTableMissEntry(BigInteger dpnId) { + setupTableMissSmacFlow(dpnId); + setupTableMissDmacFlow(dpnId); + } + + private void setupTableMissSmacFlow(BigInteger dpId) { + List mkMatches = new ArrayList(); + List mkInstructions = new ArrayList(); + List actionsInfos = new ArrayList (); + actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {})); + mkInstructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos)); + mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { ElanConstants.ELAN_DMAC_TABLE })); + + FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, ElanConstants.ELAN_SMAC_TABLE, getTableMissFlowRef(ElanConstants.ELAN_SMAC_TABLE), + 0, "ELAN sMac Table Miss Flow", 0, 0, ElanConstants.COOKIE_ELAN_KNOWN_SMAC, + mkMatches, mkInstructions); + mdsalManager.installFlow(flowEntity); + } + + private void setupTableMissDmacFlow(BigInteger dpId) { + List mkMatches = new ArrayList(); + + List mkInstructions = new ArrayList(); + mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { ElanConstants.ELAN_UNKNOWN_DMAC_TABLE })); + + FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, ElanConstants.ELAN_DMAC_TABLE, getTableMissFlowRef(ElanConstants.ELAN_DMAC_TABLE), + 0, "ELAN dMac Table Miss Flow", 0, 0, ElanConstants.COOKIE_ELAN_KNOWN_DMAC, + mkMatches, mkInstructions); + mdsalManager.installFlow(flowEntity); + } + + private String getTableMissFlowRef(long tableId) { + return new StringBuffer().append(tableId).toString(); + } +} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanPacketInHandler.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanPacketInHandler.java new file mode 100755 index 00000000..04de7e3a --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanPacketInHandler.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.internal; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.vpnservice.elan.utils.ElanConstants; +import org.opendaylight.vpnservice.elan.utils.ElanUtils; +//import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo; +import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo; +import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager; +import org.opendaylight.vpnservice.mdsalutil.MDSALUtil; +import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil; +import org.opendaylight.vpnservice.mdsalutil.NWUtil; +import org.opendaylight.controller.liblldp.NetUtils; +import org.opendaylight.vpnservice.mdsalutil.packet.Ethernet; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.NoMatch; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketInReason; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.state.Elan; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.tag.name.map.ElanTagName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntryBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntryKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._if.indexes._interface.map.IfIndexInterface; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigInteger; + +public class ElanPacketInHandler implements PacketProcessingListener { + + private final DataBroker broker; + private IInterfaceManager interfaceManager; + + private static final Logger logger = LoggerFactory.getLogger(ElanPacketInHandler.class); + + public ElanPacketInHandler(DataBroker dataBroker) { + broker = dataBroker; + } + + public void setInterfaceManager(IInterfaceManager interfaceManager) { + this.interfaceManager = interfaceManager; + } + + @Override + public void onPacketReceived(PacketReceived notification) { + Class pktInReason = notification.getPacketInReason(); + short tableId = notification.getTableId().getValue(); + if(pktInReason == NoMatch.class && tableId == ElanConstants.ELAN_SMAC_TABLE) { + try { + byte[] data = notification.getPayload(); + Ethernet res = new Ethernet(); + + res.deserialize(data, 0, data.length * NetUtils.NumBitsInAByte); + + byte[] srcMac = res.getSourceMACAddress(); + String macAddress = NWUtil.toStringMacAddress(srcMac); + PhysAddress physAddress = new PhysAddress(macAddress); + BigInteger metadata = notification.getMatch().getMetadata().getMetadata(); + long elanTag = MetaDataUtil.getElanTagFromMetadata(metadata); + + long portTag = MetaDataUtil.getLportFromMetadata(metadata).intValue(); + + IfIndexInterface interfaceInfo = ElanUtils.getInterfaceInfoByInterfaceTag(portTag); + if (interfaceInfo == null) { + logger.warn("There is no interface for given portTag {}", portTag); + return; + } + String interfaceName = interfaceInfo.getInterfaceName(); + ElanTagName elanTagName = ElanUtils.getElanInfoByElanTag(elanTag); + String elanName = elanTagName.getName(); + Elan elanInfo = ElanUtils.getElanByName(elanName); + MacEntry macEntry = ElanUtils.getInterfaceMacEntriesOperationalDataPath(interfaceName, physAddress); + if(macEntry != null && macEntry.getInterface() == interfaceName) { + BigInteger macTimeStamp = macEntry.getControllerLearnedForwardingEntryTimestamp(); + if (System.currentTimeMillis() > macTimeStamp.longValue()+2000) { + /* + * Protection time expired. Even though the MAC has been learnt (it is in the cache) + * the packets are punted to controller. Which means, the the flows were not successfully + * created in the DPN, but the MAC entry has been added successfully in the cache. + * + * So, the cache has to be cleared and the flows and cache should be recreated (clearing + * of cache is required so that the timestamp is updated). + */ + InstanceIdentifier macEntryId = ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress); + ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, macEntryId); + } else { + // Protection time running. Ignore packets for 2 seconds + return; + } + } else if(macEntry != null) { + // MAC address has moved. Overwrite the mapping and replace MAC flows + long macTimeStamp = macEntry.getControllerLearnedForwardingEntryTimestamp().longValue(); + if (System.currentTimeMillis() > macTimeStamp+1000) { + + InstanceIdentifier macEntryId = ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress); + ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, macEntryId); + tryAndRemoveInvalidMacEntry(elanName, macEntry); + } else { + // New FEs flood their packets on all interfaces. This can lead + // to many contradicting packet_ins. Ignore all packets received + // within 1s after the first packet_in + return; + } + } + BigInteger timeStamp = new BigInteger(String.valueOf((long)System.currentTimeMillis())); + macEntry = new MacEntryBuilder().setInterface(interfaceName).setMacAddress(physAddress).setKey(new MacEntryKey(physAddress)).setControllerLearnedForwardingEntryTimestamp(timeStamp).setIsStaticAddress(false).build(); + InstanceIdentifier macEntryId = ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, macEntryId, macEntry); + InstanceIdentifier elanMacEntryId = ElanUtils.getMacEntryOperationalDataPath(elanName, physAddress); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, elanMacEntryId, macEntry); + ElanInstance elanInstance = ElanUtils.getElanInstanceByName(elanName); + ElanUtils.setupMacFlows(elanInstance, interfaceManager.getInterfaceInfo(interfaceName), elanInstance.getMacTimeout(), macAddress); + } catch (Exception e) { + logger.trace("Failed to decode packet: {}", e); + } + } + + } + + + /* + * Though this method is a little costlier because it uses try-catch construct, it is used + * only in rare scenarios like MAC movement or invalid Static MAC having been added on a + * wrong ELAN. + */ + private void tryAndRemoveInvalidMacEntry(String elanName, MacEntry macEntry) { + ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanName); + if (elanInfo == null) { + logger.warn(String.format("MAC %s is been added (either statically or dynamically) for an invalid Elan %s. " + + "Manual cleanup may be necessary", macEntry.getMacAddress(), elanName)); + return; + } + + InterfaceInfo oldInterfaceLport = interfaceManager.getInterfaceInfo(macEntry.getInterface()); + if (oldInterfaceLport == null) { + logger.warn(String.format("MAC %s is been added (either statically or dynamically) on an invalid Logical Port %s. " + + "Manual cleanup may be necessary", macEntry.getMacAddress(), macEntry.getInterface())); + return; + } + ElanUtils.deleteMacFlows(elanInfo, oldInterfaceLport, macEntry); + } + +} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanServiceProvider.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanServiceProvider.java new file mode 100644 index 00000000..9b8eb446 --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanServiceProvider.java @@ -0,0 +1,402 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.internal; + +import com.google.common.base.Optional; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.NotificationService; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext; +import org.opendaylight.controller.sal.binding.api.BindingAwareProvider; +import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; +import org.opendaylight.elanmanager.api.IElanService; +import org.opendaylight.vpnservice.elan.statisitcs.ElanStatisticsImpl; +import org.opendaylight.vpnservice.elan.utils.ElanConstants; +import org.opendaylight.vpnservice.elan.utils.ElanUtils; +import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager; +import org.opendaylight.vpnservice.itm.api.IITMProvider; +import org.opendaylight.vpnservice.mdsalutil.MDSALUtil; +import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanInstances; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanInterfaces; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstanceBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstanceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterfaceBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.state.Elan; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.statistics.rev150824.ElanStatisticsService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.elanmanager.exceptions.MacNotFoundException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.Future; + +public class ElanServiceProvider implements BindingAwareProvider, IElanService, AutoCloseable { + + private IdManagerService idManager; + private IMdsalApiManager mdsalManager; + private IInterfaceManager interfaceManager; + private OdlInterfaceRpcService interfaceManagerRpcService; + private ElanInstanceManager elanInstanceManager; + private ElanForwardingEntriesHandler elanForwardingEntriesHandler; + private ElanInterfaceManager elanInterfaceManager; + private ElanPacketInHandler elanPacketInHandler; + private ElanSmacFlowEventListener elanSmacFlowEventListener; + private ElanNodeListener elanNodeListener; + private NotificationService notificationService; + private RpcProviderRegistry rpcProviderRegistry; + + public ElanServiceProvider(RpcProviderRegistry rpcRegistry) { + rpcProviderRegistry = rpcRegistry; + } + + //private ElanInterfaceEventListener elanInterfaceEventListener; + private ElanItmEventListener elanItmEventListener; + private IITMProvider itmManager; + private DataBroker broker; + + private static final Logger logger = LoggerFactory.getLogger(ElanServiceProvider.class); + + @Override + public void onSessionInitiated(ProviderContext session) { + createIdPool(); + broker = session.getSALService(DataBroker.class); + + elanForwardingEntriesHandler = new ElanForwardingEntriesHandler(broker, mdsalManager); + elanForwardingEntriesHandler.setIITMManager(itmManager); + + elanInterfaceManager = ElanInterfaceManager.getElanInterfaceManager(); + elanInterfaceManager.setInterfaceManager(interfaceManager); + elanInterfaceManager.setIdManager(idManager); + elanInterfaceManager.setMdSalApiManager(mdsalManager); + elanInterfaceManager.setDataBroker(broker); + elanInterfaceManager.setIITMManager(itmManager); + elanInterfaceManager.registerListener(); + elanInterfaceManager.setInterfaceManagerRpcService(interfaceManagerRpcService); + elanInterfaceManager.setElanForwardingEntriesHandler(elanForwardingEntriesHandler); + + elanInstanceManager = ElanInstanceManager.getElanInstanceManager(); + elanInstanceManager.setDataBroker(broker); + elanInstanceManager.setIdManager(idManager); + elanInstanceManager.setElanInterfaceManager(elanInterfaceManager); + elanInstanceManager.registerListener(); + + elanNodeListener = new ElanNodeListener(broker, mdsalManager); + + elanPacketInHandler = new ElanPacketInHandler(broker); + elanPacketInHandler.setInterfaceManager(interfaceManager); + notificationService.registerNotificationListener(elanPacketInHandler); + + elanSmacFlowEventListener = new ElanSmacFlowEventListener(broker); + elanSmacFlowEventListener.setMdSalApiManager(mdsalManager); + elanSmacFlowEventListener.setInterfaceManager(interfaceManager); + elanSmacFlowEventListener.setIITMManager(itmManager); + elanSmacFlowEventListener.setSalFlowService(session.getRpcService(SalFlowService.class)); + notificationService.registerNotificationListener(elanSmacFlowEventListener); + + // Initialize statistics rpc provider for elan + ElanStatisticsService interfaceStatsService = new ElanStatisticsImpl(broker, interfaceManager, mdsalManager); + rpcProviderRegistry.addRpcImplementation(ElanStatisticsService.class, interfaceStatsService); + + ElanUtils.setElanServiceProvider(this); + } + + public void setIdManager(IdManagerService idManager) { + this.idManager = idManager; + } + + public void setMdsalManager(IMdsalApiManager mdsalManager) { + this.mdsalManager = mdsalManager; + } + + public void setInterfaceManager(IInterfaceManager interfaceManager) { + this.interfaceManager = interfaceManager; + } + + public IMdsalApiManager getMdsalManager() { + return mdsalManager; + } + + public IITMProvider getItmManager() { + return itmManager; + } + + public DataBroker getBroker() { + return broker; + } + + public void setNotificationService(NotificationService notificationService) { + this.notificationService = notificationService; + } + + public void setInterfaceManagerRpcService(OdlInterfaceRpcService interfaceManager) { + this.interfaceManagerRpcService = interfaceManager; + } + + public OdlInterfaceRpcService getInterfaceManagerRpcService() { + return interfaceManagerRpcService; + } + + public void setItmManager(IITMProvider itmManager) { + this.itmManager = itmManager; + } + + private void createIdPool() { + CreateIdPoolInput createPool = new CreateIdPoolInputBuilder() + .setPoolName(ElanConstants.ELAN_ID_POOL_NAME).setLow(ElanConstants.ELAN_ID_LOW_VALUE).setHigh(ElanConstants.ELAN_ID_HIGH_VALUE) + .build(); + try { + Future> result = idManager.createIdPool(createPool); + if ((result != null) && (result.get().isSuccessful())) { + logger.debug("ELAN Id Pool is created successfully"); + } + } catch (Exception e) { + logger.error("Failed to create ELAN Id pool {}", e); + } + } + + @Override + public boolean createElanInstance(String elanInstanceName, long macTimeout, String description) { + ElanInstance existingElanInstance = elanInstanceManager.getElanInstanceByName(elanInstanceName); + boolean isSuccess = true; + if(existingElanInstance != null) { + if(compareWithExistingElanInstance(existingElanInstance, macTimeout, description)) { + logger.debug("Elan Instance is already present in the Operational DS {}", existingElanInstance); + return true; + } else { + ElanInstance updateElanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName).setDescription(description).setMacTimeout(macTimeout).setKey(new ElanInstanceKey(elanInstanceName)).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInstanceConfigurationDataPath(elanInstanceName), updateElanInstance); + logger.debug("Updating the Elan Instance {} with MAC TIME-OUT %l and Description %s ", updateElanInstance, macTimeout, description); + } + } else { + ElanInstance elanInstance = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName).setMacTimeout(macTimeout).setDescription(description).setKey(new ElanInstanceKey(elanInstanceName)).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInstanceIdentifier(elanInstanceName), elanInstance); + logger.debug("Creating the new Elan Instance {}", elanInstance); + } + return isSuccess; + } + + public static boolean compareWithExistingElanInstance(ElanInstance existingElanInstance, long macTimeOut, String description) { + boolean isEqual = false; + if(existingElanInstance.getMacTimeout() == macTimeOut && existingElanInstance.getDescription().equals(description)) { + isEqual = true; + } + return isEqual; + } + @Override + public void updateElanInstance(String elanInstanceName, long newMacTimout, String newDescription) { + createElanInstance(elanInstanceName, newMacTimout, newDescription); + } + + @Override + public boolean deleteElanInstance(String elanInstanceName) { + boolean isSuccess = false; + ElanInstance existingElanInstance = elanInstanceManager.getElanInstanceByName(elanInstanceName); + if(existingElanInstance == null) { + logger.debug("Elan Instance is not present {}" , existingElanInstance); + return isSuccess; + } + logger.debug("Deletion of the existing Elan Instance {}", existingElanInstance); + ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInstanceIdentifier(elanInstanceName)); + isSuccess = true; + return isSuccess; + } + + @Override + public void addElanInterface(String elanInstanceName, String interfaceName, List staticMacAddresses, String description) { + ElanInstance existingElanInstance = elanInstanceManager.getElanInstanceByName(elanInstanceName); + if(existingElanInstance != null) { + ElanInterface elanInterface; + if(staticMacAddresses == null) { + elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName).setDescription(description).setName(interfaceName).setKey(new ElanInterfaceKey(interfaceName)).build(); + } else { + elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName).setDescription(description).setName(interfaceName).setStaticMacEntries(getPhysAddress(staticMacAddresses)).setKey(new ElanInterfaceKey(interfaceName)).build(); + } + MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface); + logger.debug("Creating the new ELan Interface {}", elanInterface); + } + + } + + @Override + public void updateElanInterface(String elanInstanceName, String interfaceName, List updatedStaticMacAddresses, String newDescription) { + ElanInterface existingElanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName); + if (existingElanInterface == null) { + return; + } + List existingMacAddress = existingElanInterface.getStaticMacEntries(); + List updatedMacAddresses = getPhysAddress(updatedStaticMacAddresses); + List updatedPhysAddress = getUpdatedPhyAddress(existingMacAddress, updatedMacAddresses); + if(updatedPhysAddress.size() > 0) { + logger.debug("updating the ElanInterface with new Mac Entries {}", updatedStaticMacAddresses); + ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName).setName(interfaceName).setDescription(newDescription).setStaticMacEntries(updatedPhysAddress).setKey(new ElanInterfaceKey(interfaceName)).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface); + } + } + + @Override + public void deleteElanInterface(String elanInstanceName, String interfaceName) { + ElanInterface existingElanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName); + if(existingElanInterface != null) { + ElanUtils.delete(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName)); + logger.debug("deleting the Elan Interface {}", existingElanInterface); + } + } + + @Override + public void addStaticMacAddress(String elanInstanceName, String interfaceName, String macAddress) { + ElanInterface existingElanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName); + PhysAddress updateStaticMacAddress = new PhysAddress(macAddress); + if (existingElanInterface != null) { + List existingMacAddress = existingElanInterface.getStaticMacEntries(); + if(existingMacAddress.contains(updateStaticMacAddress)) { + return; + } + existingMacAddress.add(updateStaticMacAddress); + ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName).setName(interfaceName).setStaticMacEntries(existingMacAddress).setDescription(existingElanInterface.getDescription()).setKey(new ElanInterfaceKey(interfaceName)).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface); + } + } + + @Override + public void deleteStaticMacAddress(String elanInstanceName, String interfaceName, String macAddress) throws MacNotFoundException { + ElanInterface existingElanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName); + PhysAddress physAddress = new PhysAddress(macAddress); + if(existingElanInterface == null) { + return; + } + List existingMacAddress = existingElanInterface.getStaticMacEntries(); + if(existingMacAddress.contains(physAddress)) { + existingMacAddress.remove(physAddress); + ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName).setName(interfaceName).setStaticMacEntries(existingMacAddress).setDescription(existingElanInterface.getDescription()).setKey(new ElanInterfaceKey(interfaceName)).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName), elanInterface); + } else { + throw new MacNotFoundException("Mac Not Found Exception"); + } + } + + @Override + public Collection getElanMacTable(String elanInstanceName) { + Elan elanInfo = ElanUtils.getElanByName(elanInstanceName); + List macAddress = new ArrayList<>(); + if(elanInfo == null) { + return macAddress; + } + List elanInterfaces = elanInfo.getElanInterfaces(); + if(elanInterfaces != null && elanInterfaces.size() > 0) { + for(String elanInterface : elanInterfaces) { + ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(elanInterface); + if(elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null && elanInterfaceMac.getMacEntry().size() > 0){ + macAddress.addAll(elanInterfaceMac.getMacEntry()); + } + } + } + return macAddress; + } + + @Override + public void flushMACTable(String elanInstanceName) { + Elan elanInfo = ElanUtils.getElanByName(elanInstanceName); + if(elanInfo == null) { + return; + } + List elanInterfaces = elanInfo.getElanInterfaces(); + if (elanInterfaces == null || elanInterfaces.isEmpty()) { + return; + } + for (String elanInterface : elanInterfaces) { + ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(elanInterface); + if (elanInterfaceMac.getMacEntry() != null && elanInterfaceMac.getMacEntry().size() > 0) { + List macEntries = elanInterfaceMac.getMacEntry(); + for(MacEntry macEntry : macEntries) { + try { + deleteStaticMacAddress(elanInstanceName, elanInterface, macEntry.getMacAddress().getValue()); + } catch (MacNotFoundException e) { + logger.error("Mac Not Found Exception {}", e); + e.printStackTrace(); + } + } + } + } + + } + + @Override + public void close() throws Exception { + elanInstanceManager.close(); + } + + public static List getPhysAddress(List macAddress) { + List physAddresses = new ArrayList<>(); + for(String mac : macAddress) { + physAddresses.add(new PhysAddress(mac)); + } + return physAddresses; + } + + + public List getUpdatedPhyAddress(List originalAddresses, List updatePhyAddresses) { + if(updatePhyAddresses != null && !updatePhyAddresses.isEmpty()) { + List existingClonedPhyAddress = new ArrayList<>(); + if (originalAddresses != null && !originalAddresses.isEmpty()) { + existingClonedPhyAddress.addAll(0, originalAddresses); + originalAddresses.removeAll(updatePhyAddresses); + updatePhyAddresses.removeAll(existingClonedPhyAddress); + } + } + return updatePhyAddresses; + } + + @Override + public ElanInstance getElanInstance(String elanName) { + return ElanUtils.getElanInstanceByName(elanName); + } + + @Override + public List getElanInstances() { + List elanList = new ArrayList(); + InstanceIdentifier elanInstancesIdentifier = InstanceIdentifier.builder(ElanInstances.class).build(); + Optional elansOptional = ElanUtils.read(broker, LogicalDatastoreType.CONFIGURATION, elanInstancesIdentifier); + if(elansOptional.isPresent()) { + elanList.addAll(elansOptional.get().getElanInstance()); + } + return elanList; + } + + @Override + public List getElanInterfaces(String elanInstanceName) { + List elanInterfaces = new ArrayList<>(); + InstanceIdentifier elanInterfacesIdentifier = InstanceIdentifier.builder(ElanInterfaces.class).build(); + Optional elanInterfacesOptional = ElanUtils.read(broker, LogicalDatastoreType.CONFIGURATION, elanInterfacesIdentifier); + if(!elanInterfacesOptional.isPresent()) { + return elanInterfaces; + } + List elanInterfaceList = elanInterfacesOptional.get().getElanInterface(); + for(ElanInterface elanInterface : elanInterfaceList) { + if(elanInterface.getElanInstanceName().equals(elanInstanceName)) { + elanInterfaces.add(elanInterface.getName()); + } + } + return elanInterfaces; + } +} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanSmacFlowEventListener.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanSmacFlowEventListener.java new file mode 100644 index 00000000..e2cb47b6 --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/internal/ElanSmacFlowEventListener.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.internal; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.vpnservice.elan.utils.ElanConstants; +import org.opendaylight.vpnservice.elan.utils.ElanUtils; +import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo; +import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager; +import org.opendaylight.vpnservice.itm.api.IITMProvider; +import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil; +import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.tag.name.map.ElanTagName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._if.indexes._interface.map.IfIndexInterface; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331._if.indexes._interface.map.IfIndexInterface; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigInteger; + +public class ElanSmacFlowEventListener implements SalFlowListener { + private final DataBroker broker; + private IMdsalApiManager mdsalManager; + private IInterfaceManager interfaceManager; + private IITMProvider itmManager; + private static final Logger logger = LoggerFactory.getLogger(ElanSmacFlowEventListener.class); + + public ElanSmacFlowEventListener(DataBroker dataBroker) { + broker = dataBroker; + } + private SalFlowService salFlowService; + + public SalFlowService getSalFlowService() { + return this.salFlowService; + } + + public void setSalFlowService(final SalFlowService salFlowService) { + this.salFlowService = salFlowService; + } + public void setInterfaceManager(IInterfaceManager interfaceManager) { + this.interfaceManager = interfaceManager; + } + + + public void setIITMManager(IITMProvider itmManager) { + this.itmManager = itmManager; + } + public void setMdSalApiManager(IMdsalApiManager mdsalManager) { + this.mdsalManager = mdsalManager; + } + @Override + public void onFlowAdded(FlowAdded arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void onFlowRemoved(FlowRemoved arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void onFlowUpdated(FlowUpdated arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void onNodeErrorNotification(NodeErrorNotification arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void onNodeExperimenterErrorNotification(NodeExperimenterErrorNotification arg0) { + // TODO Auto-generated method stub + + } + + @Override + public void onSwitchFlowRemoved(SwitchFlowRemoved switchFlowRemoved) { + short tableId = switchFlowRemoved.getTableId(); + if (tableId == ElanConstants.ELAN_SMAC_TABLE) { + BigInteger metadata = switchFlowRemoved.getMatch().getMetadata().getMetadata(); + long elanTag = MetaDataUtil.getElanTagFromMetadata(metadata); + ElanTagName elanTagInfo = ElanUtils.getElanInfoByElanTag(elanTag); + if (elanTagInfo == null) { + return; + } + String srcMacAddress = switchFlowRemoved.getMatch().getEthernetMatch() + .getEthernetSource().getAddress().getValue().toUpperCase(); + int portTag = MetaDataUtil.getLportFromMetadata(metadata).intValue(); + if (portTag == 0) { + logger.debug(String.format("Flow removed event on SMAC flow entry. But having port Tag as 0 ")); + return; + } + IfIndexInterface existingInterfaceInfo = ElanUtils.getInterfaceInfoByInterfaceTag(portTag); + String interfaceName = existingInterfaceInfo.getInterfaceName(); + PhysAddress physAddress = new PhysAddress(srcMacAddress); + if (interfaceName == null) { + logger.error(String.format("LPort record not found for tag %d", portTag)); + return; + } + MacEntry macEntry = ElanUtils.getInterfaceMacEntriesOperationalDataPath(interfaceName, physAddress); + InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName); + if(macEntry != null && interfaceInfo != null) { + ElanUtils.deleteMacFlows(ElanUtils.getElanInstanceByName(elanTagInfo.getName()), interfaceInfo, macEntry); + } + InstanceIdentifier macEntryId = ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress); + ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, macEntryId); + } + } + +} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/statisitcs/ElanStatisticsImpl.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/statisitcs/ElanStatisticsImpl.java new file mode 100755 index 00000000..7f927dda --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/statisitcs/ElanStatisticsImpl.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.statisitcs; + +import com.google.common.util.concurrent.Futures; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.vpnservice.elan.utils.ElanConstants; +import org.opendaylight.vpnservice.elan.utils.ElanUtils; +//import org.opendaylight.vpnservice.ericsson.mdsalutil.statistics.StatValue; +//import org.opendaylight.vpnservice.ericsson.mdsalutil.statistics.StatisticsInfo; +import org.opendaylight.vpnservice.interfacemgr.exceptions.InterfaceNotFoundException; +import org.opendaylight.vpnservice.interfacemgr.exceptions.InterfaceServiceNotFoundException; +import org.opendaylight.vpnservice.interfacemgr.globals.IfmConstants; +import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo; +import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceServiceUtil; +import org.opendaylight.vpnservice.interfacemgr.globals.VlanInterfaceInfo; +import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager; +import org.opendaylight.vpnservice.mdsalutil.MatchInfo; +import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice._interface.service.rev150602._interface.service.info.ServiceInfo; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice._interface.statistics.rev150824.ResultCode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.statistics.rev150824.ElanStatisticsService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.statistics.rev150824.GetElanInterfaceStatisticsInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.statistics.rev150824.GetElanInterfaceStatisticsOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.statistics.rev150824.GetElanInterfaceStatisticsOutputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.statistics.rev150824.get.elan._interface.statistics.output.StatResultBuilder; +import org.opendaylight.yangtools.yang.common.RpcError.ErrorType; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.RpcResultBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.ServicesInfo; + +import java.math.BigInteger; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Future; + +public class ElanStatisticsImpl implements ElanStatisticsService { + private DataBroker dataBroker; + private IInterfaceManager interfaceManager; + private IMdsalApiManager mdsalMgr; + private static final Logger logger = LoggerFactory.getLogger(ElanStatisticsImpl.class); + + public ElanStatisticsImpl(DataBroker dataBroker, IInterfaceManager interfaceManager, + IMdsalApiManager mdsalMgr) { + this.interfaceManager = interfaceManager; + this.dataBroker = dataBroker; + this.mdsalMgr = mdsalMgr; + } + + @Override + public Future> getElanInterfaceStatistics( + GetElanInterfaceStatisticsInput input) { + String interfaceName = input.getInterfaceName(); + logger.debug("getElanInterfaceStatistics is called for elan interface {}", interfaceName); + RpcResultBuilder rpcResultBuilder = null; + if (interfaceName == null) { + rpcResultBuilder = RpcResultBuilder.failed(); + return getFutureWithAppErrorMessage(rpcResultBuilder, "Interface name is not provided"); + } + ElanInterface elanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName); + if (elanInterface == null) { + rpcResultBuilder = RpcResultBuilder.failed(); + return getFutureWithAppErrorMessage(rpcResultBuilder, String.format("Interface %s is not a ELAN interface", interfaceName)); + } + String elanInstanceName = elanInterface.getElanInstanceName(); + ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanInstanceName); + long elanTag = elanInfo.getElanTag(); + InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName); + ServicesInfo serviceInfo = ElanUtils.getServiceInfo(elanInstanceName, elanTag, interfaceName); + //FIXME [ELANBE] Get this API Later + short tableId = 0; +// try { +// +// //tableId = interfaceManager.getTableIdForService(interfaceName, serviceInfo); +// } catch (InterfaceNotFoundException | InterfaceServiceNotFoundException e) { +// rpcResultBuilder = RpcResultBuilder.failed(); +// return getFutureWithAppErrorMessage(rpcResultBuilder, String.format("Interface %s or Service %s doesn't exist", interfaceName, serviceInfo)); +// } + if (!interfaceInfo.isOperational()) { + logger.debug("interface {} is down and returning with no statistics", interfaceName); + rpcResultBuilder = RpcResultBuilder.success(); + return Futures.immediateFuture(rpcResultBuilder.withResult(new GetElanInterfaceStatisticsOutputBuilder().setStatResult(new StatResultBuilder() + .setStatResultCode(ResultCode.NotFound).setByteRxCount(0L).setByteTxCount(0L).setPacketRxCount(0L) + .setPacketTxCount(0L).build()).build()).build()); + } + rpcResultBuilder = RpcResultBuilder.success(); + return Futures.immediateFuture(rpcResultBuilder.withResult(queryforElanInterfaceStatistics(tableId, elanInstanceName, interfaceInfo)).build()); + } + + private GetElanInterfaceStatisticsOutput queryforElanInterfaceStatistics(short tableId, String elanInstanceName, InterfaceInfo interfaceInfo) { + BigInteger dpId = interfaceInfo.getDpId(); + List matches = null; + String interfaceName = interfaceInfo.getInterfaceName(); + if (tableId == IfmConstants.VLAN_INTERFACE_INGRESS_TABLE) { + VlanInterfaceInfo vlanInterfaceInfo = (VlanInterfaceInfo)interfaceInfo; + matches = InterfaceServiceUtil.getMatchInfoForVlanLPort(dpId, interfaceInfo.getPortNo(), + InterfaceServiceUtil.getVlanId(interfaceName, dataBroker), vlanInterfaceInfo.isVlanTransparent()); + } else { + matches = InterfaceServiceUtil.getLPortDispatcherMatches(ElanConstants.ELAN_SERVICE_INDEX, interfaceInfo.getInterfaceTag()); + } + long groupId = interfaceInfo.getGroupId(); + Set statRequestKeys = InterfaceServiceUtil.getStatRequestKeys(dpId, tableId, matches, String.format("%s.%s", elanInstanceName, interfaceName), groupId); + // StatisticsInfo statsInfo = new StatisticsInfo(statRequestKeys); +// org.opendaylight.vpnservice.ericsson.mdsalutil.statistics.StatResult statResult = mdsalMgr.queryForStatistics(interfaceName, statsInfo); +// ResultCode resultCode = ResultCode.Success; +// if (!statResult.isComplete()) { +// resultCode = ResultCode.Incomplete; +// } + + //StatValue ingressFlowStats = statResult.getStatResult(InterfaceServiceUtil.getFlowStatisticsKey(dpId, tableId, matches, elanInstanceName)); + //StatValue groupStats = statResult.getStatResult(InterfaceServiceUtil.getGroupStatisticsKey(dpId, groupId)); +// return new GetElanInterfaceStatisticsOutputBuilder().setStatResult(new StatResultBuilder().setStatResultCode(resultCode) +// .setByteRxCount(ingressFlowStats.getByteCount()).setPacketRxCount(ingressFlowStats.getPacketCount()) +// .setByteTxCount(groupStats.getByteCount()).setPacketTxCount(groupStats.getPacketCount()).build()).build(); + return null; + } + + private Future> getFutureWithAppErrorMessage( + RpcResultBuilder rpcResultBuilder, String message) { + rpcResultBuilder.withError(ErrorType.APPLICATION, message); + return Futures.immediateFuture(rpcResultBuilder.build()); + } + +} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/utils/ElanCLIUtils.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/utils/ElanCLIUtils.java new file mode 100644 index 00000000..0add3032 --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/utils/ElanCLIUtils.java @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.utils; + +public class ElanCLIUtils { + public static final String HEADER_UNDERLINE = "----------------------------------------------------------------------------------------------"; + public static final String MAC_TABLE_CLI_FORMAT = "%-35s %-20s %-20s %-20s"; + public static final String ELAN_CLI_FORMAT = "%-35s %-20s %-20s "; + public static final String ELAN_INTERFACE_CLI_FORMAT = "%-35s %-25s %-15s %-15s "; +} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/utils/ElanConstants.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/utils/ElanConstants.java new file mode 100755 index 00000000..a4afd5be --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/utils/ElanConstants.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.utils; + +import java.math.BigInteger; + +public class ElanConstants { + + public static final String ELAN_ID_POOL_NAME = "elan.ids.pool"; + public static final long ELAN_ID_LOW_VALUE = 5000L; + public static final long ELAN_ID_HIGH_VALUE = 10000L; + public static final int ELAN_GID_MIN = 200000; + public static final short ELAN_SMAC_TABLE = 50; + public static final short ELAN_DMAC_TABLE = 51; + public static final short ELAN_UNKNOWN_DMAC_TABLE = 52; + public static final short ELAN_SERVICE_INDEX = 3; + public static final int ELAN_SERVICE_PRIORITY = 5; + public static final int STATIC_MAC_TIMEOUT = 0; + public static final long DELAY_TIME_IN_MILLISECOND = 10000; + public static final BigInteger INVALID_DPN = BigInteger.valueOf(-1); + public static final BigInteger COOKIE_ELAN_UNKNOWN_DMAC = new BigInteger("8700000", 16); + public static final BigInteger COOKIE_ELAN_KNOWN_SMAC = new BigInteger("8050000", 16); + public static final BigInteger COOKIE_ELAN_KNOWN_DMAC = new BigInteger("8030000", 16); + public static final BigInteger COOKIE_ELAN_INGRESS_TABLE = new BigInteger("8040000", 16); + public static final long DEFAULT_MAC_TIME_OUT = 30; + public static final short ELAN_FILTER_EQUALS_TABLE = 55; + public static final BigInteger COOKIE_ELAN_FILTER_EQUALS = new BigInteger("8800000", 16); + + +} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/utils/ElanUtils.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/utils/ElanUtils.java new file mode 100644 index 00000000..0ffbf639 --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/vpnservice/elan/utils/ElanUtils.java @@ -0,0 +1,795 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.elan.utils; + +import com.google.common.base.Optional; +import com.google.common.util.concurrent.FutureCallback; +import com.google.common.util.concurrent.Futures; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.vpnservice.elan.internal.ElanInstanceManager; +import com.google.common.util.concurrent.CheckedFuture; +import org.opendaylight.vpnservice.elan.internal.ElanServiceProvider; +import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo; +import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceServiceUtil; +import org.opendaylight.vpnservice.itm.api.IITMProvider; +import org.opendaylight.vpnservice.mdsalutil.*; +import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; +import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.OutputActionCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice._interface.service.rev150602._interface.service.info.ServiceInfo; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.ExtensionKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlowBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.grouping.ExtensionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionListBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.reg.grouping.NxmNxRegBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMacKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesListKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfacesKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.forwarding.tables.MacTable; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.forwarding.tables.MacTableBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.forwarding.tables.MacTableKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstanceBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstanceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.state.Elan; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.state.ElanBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.state.ElanKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.tag.name.map.ElanTagName; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.tag.name.map.ElanTagNameBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.tag.name.map.ElanTagNameKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntryKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.*; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfIndexesInterfaceMap; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331._if.indexes._interface.map.IfIndexInterface; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331._if.indexes._interface.map.IfIndexInterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceOutput; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.IfIndexesInterfaceMap; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._if.indexes._interface.map.IfIndexInterface; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._if.indexes._interface.map.IfIndexInterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.ServicesInfo; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.ServiceBindings; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.ServiceTypeFlowBased; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.StypeOpenflow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.StypeOpenflowBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.ServicesInfoKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServicesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServicesKey; + + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +public class ElanUtils { + + private static ElanServiceProvider elanServiceProvider; + private static final Logger logger = LoggerFactory.getLogger(ElanUtils.class); + + public static final FutureCallback DEFAULT_CALLBACK = + new FutureCallback() { + public void onSuccess(Void result) { + logger.debug("Success in Datastore operation"); + } + + public void onFailure(Throwable error) { + logger.error("Error in Datastore operation", error); + }; + }; + + public static Integer getUniqueId(IdManagerService idManager, String poolName, String idKey) { + AllocateIdInput getIdInput = new AllocateIdInputBuilder() + .setPoolName(poolName) + .setIdKey(idKey).build(); + + try { + Future> result = idManager.allocateId(getIdInput); + RpcResult rpcResult = result.get(); + if(rpcResult.isSuccessful()) { + return rpcResult.getResult().getIdValue().intValue(); + } else { + logger.warn("RPC Call to Allocate Id returned with Errors {}", rpcResult.getErrors()); + } + } catch (InterruptedException | ExecutionException e) { + logger.warn("Exception when Allocating Id",e); + } + return 0; + } + + public static void setElanServiceProvider(ElanServiceProvider elanService) { + elanServiceProvider = elanService; + } + public static void releaseId(IdManagerService idManager, String poolName, String idKey) { + ReleaseIdInput releaseIdInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build(); + Future> result = idManager.releaseId(releaseIdInput); + } + + public static Optional read(DataBroker broker, LogicalDatastoreType datastoreType, + InstanceIdentifier path) { + + ReadOnlyTransaction tx = broker.newReadOnlyTransaction(); + + Optional result = Optional.absent(); + try { + result = tx.read(datastoreType, path).get(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + return result; + } + + + public static void delete(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier path) { + WriteTransaction tx = broker.newWriteOnlyTransaction(); + tx.delete(datastoreType, path); + Futures.addCallback(tx.submit(), DEFAULT_CALLBACK); + } + + public static InstanceIdentifier getElanInstanceIdentifier(String elanName) { + return InstanceIdentifier.builder(ElanInstances.class) + .child(ElanInstance.class, new ElanInstanceKey(elanName)).build(); + } + + public static InstanceIdentifier getElanInstanceIdentifier() { + return InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class).build(); + } + + //elan-instances config container + public static ElanInstance getElanInstanceByName(String elanInstanceName) { + DataBroker broker = elanServiceProvider.getBroker(); + InstanceIdentifier elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName); + Optional elanInstance = read(broker, LogicalDatastoreType.CONFIGURATION, elanIdentifierId); + if(elanInstance.isPresent()) { + return elanInstance.get(); + } + return null; + } + + public static InstanceIdentifier getElanInstanceConfigurationDataPath(String elanInstanceName) { + return InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build(); + } + + //elan-interfaces Config Container + public static ElanInterface getElanInterfaceByElanInterfaceName(String elanInterfaceName) { + DataBroker broker = elanServiceProvider.getBroker(); + InstanceIdentifier elanInterfaceId = getElanInterfaceConfigurationDataPathId(elanInterfaceName); + Optional existingElanInterface = read(broker, LogicalDatastoreType.CONFIGURATION, elanInterfaceId); + if(existingElanInterface.isPresent()) { + return existingElanInterface.get(); + } + return null; + } + + public static class RegMatch { + + final Class reg; + final Long value; + + public RegMatch(Class reg, Long value) { + super(); + this.reg = reg; + this.value = value; + } + + public static RegMatch of(Class reg, Long value) { + return new RegMatch(reg, value); + } + } + + public static void addNxRegMatch(MatchBuilder match, RegMatch... matches) { + ArrayList extensions = new ArrayList<>(); + for (RegMatch rm : matches) { + Class key; + if (NxmNxReg0.class.equals(rm.reg)) { + key = NxmNxReg0Key.class; + } else if (NxmNxReg1.class.equals(rm.reg)) { + key = NxmNxReg1Key.class; + } else if (NxmNxReg2.class.equals(rm.reg)) { + key = NxmNxReg2Key.class; + } else if (NxmNxReg3.class.equals(rm.reg)) { + key = NxmNxReg3Key.class; + } else if (NxmNxReg4.class.equals(rm.reg)) { + key = NxmNxReg4Key.class; + } else if (NxmNxReg5.class.equals(rm.reg)) { + key = NxmNxReg5Key.class; + } else if (NxmNxReg6.class.equals(rm.reg)) { + key = NxmNxReg6Key.class; + } else { + key = NxmNxReg7Key.class; + } + NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxReg( + new NxmNxRegBuilder().setReg(rm.reg).setValue(rm.value).build()).build(); + extensions.add(new ExtensionListBuilder().setExtensionKey(key) + .setExtension(new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build()) + .build()); + } + GeneralAugMatchNodesNodeTableFlow m = new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList( + extensions).build(); + match.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m); + } + + public static InstanceIdentifier getElanInterfaceConfigurationDataPathId(String interfaceName) { + return InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface.class, + new ElanInterfaceKey(interfaceName)).build(); + } + + //elan-state Operational container + public static Elan getElanByName(String elanInstanceName) { + DataBroker broker = elanServiceProvider.getBroker(); + InstanceIdentifier elanIdentifier = getElanInstanceOperationalDataPath(elanInstanceName); + Optional elanInstance = read(broker, LogicalDatastoreType.OPERATIONAL, elanIdentifier); + if(elanInstance.isPresent()) { + return elanInstance.get(); + } + return null; + } + + public static InstanceIdentifier getElanInstanceOperationalDataPath(String elanInstanceName) { + return InstanceIdentifier.builder(ElanState.class).child(Elan.class, new ElanKey(elanInstanceName)).build(); + } + + // grouping of forwarding-entries + public static MacEntry getInterfaceMacEntriesOperationalDataPath(String interfaceName, PhysAddress physAddress) { + DataBroker broker = elanServiceProvider.getBroker(); + InstanceIdentifier existingMacEntryId = getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress); + Optional existingInterfaceMacEntry = read(broker, LogicalDatastoreType.OPERATIONAL, existingMacEntryId); + if(existingInterfaceMacEntry.isPresent()) { + return existingInterfaceMacEntry.get(); + } + return null; + } + + public static MacEntry getInterfaceMacEntriesOperationalDataPathFromId(InstanceIdentifier identifier) { + DataBroker broker = elanServiceProvider.getBroker(); + Optional existingInterfaceMacEntry = read(broker, LogicalDatastoreType.OPERATIONAL, identifier); + if(existingInterfaceMacEntry.isPresent()) { + return existingInterfaceMacEntry.get(); + } + return null; + } + + public static InstanceIdentifier getInterfaceMacEntriesIdentifierOperationalDataPath(String interfaceName, PhysAddress physAddress) { + return InstanceIdentifier.builder(ElanInterfaceForwardingEntries.class).child(ElanInterfaceMac.class, + new ElanInterfaceMacKey(interfaceName)).child(MacEntry.class, new MacEntryKey(physAddress)).build(); + + } + + //elan-forwarding-tables Operational container + public static MacEntry getMacTableByElanName(String elanName, PhysAddress physAddress) { + DataBroker broker = elanServiceProvider.getBroker(); + InstanceIdentifier macId = getMacEntryOperationalDataPath(elanName, physAddress); + Optional existingElanMacEntry = read(broker, LogicalDatastoreType.OPERATIONAL, macId); + if(existingElanMacEntry.isPresent()) { + return existingElanMacEntry.get(); + } + return null; + } + + + public static MacEntry getMacEntryFromElanMacId(InstanceIdentifier identifier) { + DataBroker broker = elanServiceProvider.getBroker(); + Optional existingInterfaceMacEntry = read(broker, LogicalDatastoreType.OPERATIONAL, identifier); + if(existingInterfaceMacEntry.isPresent()) { + return existingInterfaceMacEntry.get(); + } + return null; + } + + public static InstanceIdentifier getMacEntryOperationalDataPath(String elanName, PhysAddress physAddress) { + return InstanceIdentifier.builder(ElanForwardingTables.class).child(MacTable.class, + new MacTableKey(elanName)).child(MacEntry.class, new MacEntryKey(physAddress)).build(); + } + + public static InstanceIdentifier getElanMacTableOperationalDataPath(String elanName) { + return InstanceIdentifier.builder(ElanForwardingTables.class).child(MacTable.class, + new MacTableKey(elanName)).build(); + } + + //elan-interface-forwarding-entries Operational container + public static ElanInterfaceMac getElanInterfaceMacByInterfaceName(String interfaceName) { + DataBroker broker = elanServiceProvider.getBroker(); + InstanceIdentifier elanInterfaceId = getElanInterfaceMacEntriesOperationalDataPath(interfaceName); + Optional existingElanInterface = read(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId); + if(existingElanInterface.isPresent()) { + return existingElanInterface.get(); + } + return null; + } + + public static InstanceIdentifier getElanInterfaceMacEntriesOperationalDataPath(String interfaceName) { + return InstanceIdentifier.builder(ElanInterfaceForwardingEntries.class).child(ElanInterfaceMac.class, + new ElanInterfaceMacKey(interfaceName)).build(); + } + + //elan-dpn-interfaces Operational Container + public static DpnInterfaces getElanInterfaceInfoByElanDpn(String elanInstanceName, BigInteger dpId) { + DataBroker broker = elanServiceProvider.getBroker(); + InstanceIdentifier elanDpnInterfacesId = getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId); + Optional elanDpnInterfaces = read(broker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfacesId); + if(elanDpnInterfaces.isPresent()) { + return elanDpnInterfaces.get(); + } + return null; + } + + public static InstanceIdentifier getElanDpnInterfaceOperationalDataPath(String elanInstanceName, BigInteger dpId) { + return InstanceIdentifier.builder(ElanDpnInterfaces.class).child(ElanDpnInterfacesList.class, + new ElanDpnInterfacesListKey(elanInstanceName)).child(DpnInterfaces.class, new DpnInterfacesKey(dpId)).build(); + } + + //elan-tag-name-map Operational Container + public static ElanTagName getElanInfoByElanTag(long elanTag) { + DataBroker broker = elanServiceProvider.getBroker(); + InstanceIdentifier elanId = getElanInfoEntriesOperationalDataPath(elanTag); + Optional existingElanInfo = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanId); + if(existingElanInfo.isPresent()) { + return existingElanInfo.get(); + } + return null; + } + + public static InstanceIdentifier getElanInfoEntriesOperationalDataPath(long elanTag) { + return InstanceIdentifier.builder(ElanTagNameMap.class).child(ElanTagName.class, + new ElanTagNameKey(elanTag)).build(); + } + + // interface-index-tag operational container + public static IfIndexInterface getInterfaceInfoByInterfaceTag(long interfaceTag) { + DataBroker broker = elanServiceProvider.getBroker(); + InstanceIdentifier interfaceId = getInterfaceInfoEntriesOperationalDataPath(interfaceTag); + Optional existingInterfaceInfo = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId); + if(existingInterfaceInfo.isPresent()) { + return existingInterfaceInfo.get(); + } + return null; + } + + public static InstanceIdentifier getInterfaceInfoEntriesOperationalDataPath(long interfaceTag) { + return InstanceIdentifier.builder(IfIndexesInterfaceMap.class).child(IfIndexInterface.class, + new IfIndexInterfaceKey((int) interfaceTag)).build(); + } + + + + public static InstanceIdentifier getElanDpnOperationDataPath(String elanInstanceName) { + return InstanceIdentifier.builder(ElanDpnInterfaces.class).child(ElanDpnInterfacesList.class, new ElanDpnInterfacesListKey(elanInstanceName)).build(); + } + + public static ElanDpnInterfacesList getElanDpnInterfacesList(String elanName) { + DataBroker broker = elanServiceProvider.getBroker(); + InstanceIdentifier elanDpnInterfaceId = getElanDpnOperationDataPath(elanName); + Optional existingElanDpnInterfaces = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId); + if(existingElanDpnInterfaces.isPresent()) { + return existingElanDpnInterfaces.get(); + } + return null; + } + + public static ElanDpnInterfaces getElanDpnInterfacesList() { + DataBroker broker = elanServiceProvider.getBroker(); + InstanceIdentifier elanDpnInterfaceId = InstanceIdentifier.builder(ElanDpnInterfaces.class).build(); + Optional existingElanDpnInterfaces = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId); + if(existingElanDpnInterfaces.isPresent()) { + return existingElanDpnInterfaces.get(); + } + return null; + } + + public static ElanForwardingTables getElanForwardingList() { + DataBroker broker = elanServiceProvider.getBroker(); + InstanceIdentifier elanForwardingTableId = InstanceIdentifier.builder(ElanForwardingTables.class).build(); + Optional existingElanForwardingList = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanForwardingTableId); + if(existingElanForwardingList.isPresent()) { + return existingElanForwardingList.get(); + } + return null; + } + + + public static long getElanLocalBCGID(long elanTag) { + return ElanConstants.ELAN_GID_MIN + (((elanTag % ElanConstants.ELAN_GID_MIN) *2) - 1); + } + + public static long getElanRemoteBCGID(long elanTag) { + return ElanConstants.ELAN_GID_MIN + (((elanTag % ElanConstants.ELAN_GID_MIN) *2)); + } + + public static BigInteger getElanMetadataLabel(long elanTag) { + return (BigInteger.valueOf(elanTag)).shiftLeft(24); + } + + public static BigInteger getElanMetadataLabel(long elanTag, int lportTag) { + return getElanMetadataLabel(elanTag).or(MetaDataUtil.getLportTagMetaData(lportTag)); + } + + public static BigInteger getElanMetadataMask() { + return MetaDataUtil.METADATA_MASK_SERVICE.or(MetaDataUtil.METADATA_MASK_LPORT_TAG); + } + + public static void setupMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, long macTimeout, + String macAddress) { + IMdsalApiManager mdsalApiManager = elanServiceProvider.getMdsalManager(); + DataBroker broker = elanServiceProvider.getBroker(); + IITMProvider itmManager = elanServiceProvider.getItmManager(); + synchronized (macAddress) { + logger.info("Acquired lock for mac : " + macAddress + "Proceeding with install operation."); + setupKnownSmacFlow(elanInfo, interfaceInfo, macTimeout, macAddress, mdsalApiManager); + setupTermDmacFlows(interfaceInfo, itmManager); + setupOrigDmacFlows(elanInfo, interfaceInfo, macAddress, mdsalApiManager, broker); + } + } + + public static void setupDMacFlowonRemoteDpn(ElanInstance elanInfo, InterfaceInfo interfaceInfo, BigInteger dstDpId, + String macAddress) { + synchronized (macAddress) { + logger.info("Acquired lock for mac : " + macAddress + "Proceeding with install operation."); + setupOrigDmacFlowsonRemoteDpn(elanInfo, interfaceInfo, dstDpId, macAddress); + } + } + + + private static void setupKnownSmacFlow(ElanInstance elanInfo, InterfaceInfo interfaceInfo, long macTimeout, + String macAddress, IMdsalApiManager mdsalApiManager) { + FlowEntity flowEntity = getKnownSmacFlowEntity(elanInfo, interfaceInfo, macTimeout, macAddress); + mdsalApiManager.installFlow(flowEntity); + if (logger.isDebugEnabled()) { + logger.debug("Known Smac flow entry created for elan Name:{}, logical Interface port:{} and mac address:{}", elanInfo.getElanInstanceName(), elanInfo.getDescription(), macAddress); + } + } + + private static FlowEntity getKnownSmacFlowEntity(ElanInstance elanInfo, InterfaceInfo interfaceInfo, long macTimeout, String macAddress) { + BigInteger dpId = interfaceInfo.getDpId(); + int lportTag = interfaceInfo.getInterfaceTag(); + long elanTag = elanInfo.getElanTag(); + // Matching metadata and eth_src fields + List mkMatches = new ArrayList(); + mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] { + ElanUtils.getElanMetadataLabel(elanInfo.getElanTag(), lportTag), + ElanUtils.getElanMetadataMask() })); + mkMatches.add(new MatchInfo(MatchFieldType.eth_src, new String[] { macAddress })); + List mkInstructions = new ArrayList(); + mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { ElanConstants.ELAN_DMAC_TABLE })); + + FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, ElanConstants.ELAN_SMAC_TABLE, + getKnownDynamicmacFlowRef(ElanConstants.ELAN_SMAC_TABLE, dpId, lportTag, macAddress, elanTag), + 20, elanInfo.getDescription(), (int)macTimeout, 0, ElanConstants.COOKIE_ELAN_KNOWN_SMAC.add(BigInteger.valueOf(elanTag)), + mkMatches, mkInstructions); + flowEntity.setStrictFlag(true); + flowEntity.setSendFlowRemFlag(macTimeout != 0); //If Mac timeout is 0, the flow wont be deleted automatically, so no need to get notified + return flowEntity; + } + + private static void setupTermDmacFlows(InterfaceInfo interfaceInfo, IITMProvider itmManager) { + BigInteger dpId = interfaceInfo.getDpId(); + long lportGroupId = interfaceInfo.getGroupId(); + int lportTag = interfaceInfo.getInterfaceTag(); + List actionsInfos = new ArrayList (); + actionsInfos = getEgressActionsForInterface(interfaceInfo.getInterfaceName()); + + //FIXME [ELANBE] ITM Service API to invoke Terminating Service + //itmManager.createTerminatingServiceActions(dpId, lportTag, actionsInfos); + if (logger.isDebugEnabled()) { + logger.debug("Terminating service table flow entry created on dpn:{} for logical Interface port:{}", dpId, interfaceInfo.getPortName()); + } + } + + public static List getEgressActionsForInterface(String ifName) { + List listActionInfo = new ArrayList(); + try { + Future> result = + elanServiceProvider.getInterfaceManagerRpcService().getEgressActionsForInterface( + new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName).build()); + RpcResult rpcResult = result.get(); + System.out.println("Data is populated"); + if(!rpcResult.isSuccessful()) { + logger.warn("RPC Call to Get egress actions for interface {} returned with Errors {}", ifName, rpcResult.getErrors()); + } else { + List actions = + rpcResult.getResult().getAction(); + for (Action action : actions) { + org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action actionClass = action.getAction(); + if (actionClass instanceof OutputActionCase) { + System.out.println("Data "); + listActionInfo.add(new ActionInfo(ActionType.output, + new String[] {((OutputActionCase)actionClass).getOutputAction() + .getOutputNodeConnector().getValue()})); + } else if (actionClass instanceof PushVlanActionCase) { + listActionInfo.add(new ActionInfo(ActionType.push_vlan, new String[] {})); + } else if (actionClass instanceof SetFieldCase) { + if (((SetFieldCase)actionClass).getSetField().getVlanMatch() != null) { + int vlanVid = ((SetFieldCase)actionClass).getSetField().getVlanMatch().getVlanId().getVlanId().getValue(); + listActionInfo.add(new ActionInfo(ActionType.set_field_vlan_vid, + new String[] { Long.toString(vlanVid) })); + } + } + } + } + } catch (InterruptedException | ExecutionException e) { + logger.warn("Exception when egress actions for interface {}", ifName, e); + } + return listActionInfo; + } + + private static void setupOrigDmacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, String macAddress, + IMdsalApiManager mdsalApiManager, DataBroker broker) { + BigInteger dpId = interfaceInfo.getDpId(); + String ifName = interfaceInfo.getInterfaceName(); + long ifTag = interfaceInfo.getInterfaceTag(); + long groupId = interfaceInfo.getGroupId(); + String elanInstanceName = elanInfo.getElanInstanceName(); + List remoteFEs = getInvolvedDpnsInElan(elanInstanceName); + if(remoteFEs != null) { + for (DpnInterfaces remoteFE : remoteFEs) { + Long elanTag = elanInfo.getElanTag(); + if (remoteFE.getDpId().equals(dpId)) { + // On the local FE set up a direct output flow + setupLocalDmacFlow(elanTag, dpId, ifName, macAddress, elanInstanceName, mdsalApiManager, ifTag); + if (logger.isDebugEnabled()) { + logger.debug("Dmac flow entry created for elan Name:{}, logical port Name:{} and mac address:{} on dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, dpId); + } + } else { + if (isDpnPresent(remoteFE.getDpId())) { + // Check for the Remote DPN present in Inventory Manager + setupRemoteDmacFlow(remoteFE.getDpId(), dpId, interfaceInfo.getInterfaceTag(), elanTag, macAddress, elanInstanceName); + if (logger.isDebugEnabled()) { + logger.debug("Dmac flow entry created for elan Name:{}, logical port Name:{} and mac address:{} on dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, remoteFE.getDpId()); + } + } + } + } + } + } + + private static void setupOrigDmacFlowsonRemoteDpn(ElanInstance elanInfo, InterfaceInfo interfaceInfo, BigInteger dstDpId, String macAddress) { + BigInteger dpId = interfaceInfo.getDpId(); + String elanInstanceName = elanInfo.getElanInstanceName(); + List remoteFEs = getInvolvedDpnsInElan(elanInstanceName); + for(DpnInterfaces remoteFE: remoteFEs) { + Long elanTag = elanInfo.getElanTag(); + if (remoteFE.getDpId().equals(dstDpId)) { + // Check for the Remote DPN present in Inventory Manager + setupRemoteDmacFlow(dstDpId, dpId, interfaceInfo.getInterfaceTag(), elanTag, macAddress, elanInstanceName); + if (logger.isDebugEnabled()) { + logger.debug("Dmac flow entry created for elan Name:{}, logical port Name:{} and mac address {} on dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, remoteFE.getDpId()); + } + break; + } + } + } + + + @SuppressWarnings("unchecked") + public static List getInvolvedDpnsInElan(String elanName) { + List dpns = ElanInstanceManager.getElanInstanceManager().getElanDPNByName(elanName); + return dpns; + } + + private static void setupLocalDmacFlow(long elanTag, BigInteger dpId, String ifName, String macAddress, + String displayName, IMdsalApiManager mdsalApiManager, long ifTag) { + FlowEntity flowEntity = getLocalDmacFlowEntry(elanTag, dpId, ifName, macAddress, displayName, ifTag); + mdsalApiManager.installFlow(flowEntity); + + } + + public static String getKnownDynamicmacFlowRef(short tableId, BigInteger dpId, long lporTag, String macAddress, long elanTag) { + return new StringBuffer().append(tableId).append(elanTag).append(dpId).append(lporTag).append(macAddress).toString(); + } + + public static String getKnownDynamicmacFlowRef(short tableId, BigInteger dpId, BigInteger remoteDpId, String macAddress, long elanTag) { + return new StringBuffer().append(tableId).append(elanTag).append(dpId).append(remoteDpId).append(macAddress).toString(); + } + + public static FlowEntity getLocalDmacFlowEntry(long elanTag, BigInteger dpId, String ifName, String macAddress, + String displayName, long ifTag) { + List mkMatches = new ArrayList(); + mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] { + ElanUtils.getElanMetadataLabel(elanTag), + MetaDataUtil.METADATA_MASK_SERVICE })); + mkMatches.add(new MatchInfo(MatchFieldType.eth_dst, new String[] { macAddress })); + + List mkInstructions = new ArrayList(); + List actionsInfos = new ArrayList (); + actionsInfos.addAll(getEgressActionsForInterface(ifName)); + mkInstructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos)); + + FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, ElanConstants.ELAN_DMAC_TABLE, + getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, dpId, ifTag, macAddress, elanTag), + 20, displayName, 0, 0, ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), + mkMatches, mkInstructions); + return flowEntity; + } + + public static void setupRemoteDmacFlow(BigInteger srcDpId, BigInteger destDpId, int lportTag, long elanTag, String macAddress, + String displayName) { + IMdsalApiManager mdsalApiManager = elanServiceProvider.getMdsalManager(); + FlowEntity flowEntity = getRemoteDmacFlowEntry(srcDpId, destDpId, lportTag, elanTag, macAddress, displayName); + mdsalApiManager.installFlow(flowEntity); + } + + public static FlowEntity getRemoteDmacFlowEntry(BigInteger srcDpId, BigInteger destDpId, int lportTag, long elanTag, + String macAddress, String displayName) { + IITMProvider itmManager = elanServiceProvider.getItmManager(); + List mkMatches = new ArrayList(); + mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[]{ + ElanUtils.getElanMetadataLabel(elanTag), + MetaDataUtil.METADATA_MASK_SERVICE })); + mkMatches.add(new MatchInfo(MatchFieldType.eth_dst, new String[] { macAddress })); + + List mkInstructions = new ArrayList(); + //List of ActionInfo for the provided Source and Destination DPIDs + try { + //FIXME [ELANBE] Removing ITM API for now, will need this for multi dpn. + //List actionsInfos = itmManager.ITMIngressGetActions(srcDpId, destDpId, lportTag); + //mkInstructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos)); + } catch (Exception e) { + logger.error("Interface Not Found exception"); + } + + FlowEntity flowEntity = MDSALUtil.buildFlowEntity(srcDpId, ElanConstants.ELAN_DMAC_TABLE, + getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, srcDpId, destDpId, macAddress, elanTag), + 20, displayName, 0, 0, ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), + mkMatches, mkInstructions); + return flowEntity; + } + + public static void deleteMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, MacEntry macEntry) { + if (elanInfo == null || interfaceInfo == null) { + return; + } + String macAddress = macEntry.getMacAddress().getValue(); + synchronized (macAddress) { + logger.info("Acquired lock for mac : " + macAddress + "Proceeding with remove operation."); + deleteMacFlows(elanInfo, interfaceInfo, macAddress, true); + } + } + + public static void deleteMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, String macAddress, boolean deleteSmac) { + String elanInstanceName = elanInfo.getElanInstanceName(); + String ifName = interfaceInfo.getInterfaceName(); + long ifTag = interfaceInfo.getInterfaceTag(); + List remoteFEs = getInvolvedDpnsInElan(elanInstanceName); + IMdsalApiManager mdsalApiManager = elanServiceProvider.getMdsalManager(); + IITMProvider itmManager = elanServiceProvider.getItmManager(); + BigInteger srcdpId = interfaceInfo.getDpId(); + String displayName = elanInstanceName; + long groupId = interfaceInfo.getGroupId(); + for (DpnInterfaces dpnInterface: remoteFEs) { + Long elanTag = elanInfo.getElanTag(); + if (dpnInterface.getDpId().equals(srcdpId)) { + if(deleteSmac) { + mdsalApiManager.removeFlow(getKnownSmacFlowEntity(elanInfo, interfaceInfo, 0, macAddress)); + } + mdsalApiManager.removeFlow(getLocalDmacFlowEntry(elanTag, dpnInterface.getDpId(), ifName, macAddress, displayName, ifTag)); + + //FIXME [ELANBE] Removing ITM API for now, will need this for multi dpn. + //itmManager.removeTerminatingServiceAction(dpnInterface.getDpId(), interfaceInfo.getInterfaceTag()); + if (logger.isDebugEnabled()) { + logger.debug("All the required flows deleted for elan:{}, logical Interface port:{} and mac address:{} on dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, dpnInterface.getDpId()); + } + } else if (isDpnPresent(dpnInterface.getDpId())) { + mdsalApiManager.removeFlow( + getRemoteDmacFlowEntry(dpnInterface.getDpId(), srcdpId, interfaceInfo.getInterfaceTag(), elanTag, macAddress, + displayName)); + if (logger.isDebugEnabled()) { + logger.debug("Dmac flow entry deleted for elan:{}, logical interface port:{} and mac address:{} on dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, dpnInterface.getDpId()); + } + } + } + } + + public static void UpdateOperationalDataStore(DataBroker broker, IdManagerService idManager, ElanInstance elanInstanceAdded) { + String elanInstanceName = elanInstanceAdded.getElanInstanceName(); + long elanTag = ElanUtils.getUniqueId(idManager, ElanConstants.ELAN_ID_POOL_NAME, elanInstanceName); + Elan elanInfo = new ElanBuilder().setName(elanInstanceName).setKey(new ElanKey(elanInstanceName)).build(); + //Add the ElanState in the elan-state operational data-store + MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName), elanInfo); + //Add the ElanMacTable in the elan-mac-table operational data-store + MacTable elanMacTable = new MacTableBuilder().setKey(new MacTableKey(elanInstanceName)).build(); + MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanMacTableOperationalDataPath(elanInstanceName), elanMacTable); + ElanTagName elanTagName = new ElanTagNameBuilder().setElanTag(elanTag).setKey(new ElanTagNameKey(elanTag)).setName(elanInstanceName).build(); + //Add the ElanTag to ElanName in the elan-tag-name Operational data-store + MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInfoEntriesOperationalDataPath(elanTag), elanTagName); + ElanInstance elanInstanceWithTag = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName).setDescription(elanInstanceAdded.getDescription()).setMacTimeout(elanInstanceAdded + .getMacTimeout() == null ? ElanConstants.DEFAULT_MAC_TIME_OUT : elanInstanceAdded.getMacTimeout()).setKey(elanInstanceAdded.getKey()).setElanTag(elanTag).build(); + MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, getElanInstanceIdentifier(elanInstanceName), elanInstanceWithTag); + } + + public static boolean isDpnPresent(BigInteger dpnId) { + DataBroker broker = elanServiceProvider.getBroker(); + boolean isPresent = false; + String dpn = String.format("%s:%s", "openflow",dpnId); + NodeId nodeId = new NodeId(dpn); + InstanceIdentifier node = InstanceIdentifier.builder(Nodes.class).child(Node.class, new NodeKey(nodeId)).build(); + Optional nodePresent = read(broker, LogicalDatastoreType.OPERATIONAL, node); + if(nodePresent.isPresent()) { + isPresent = true; + } + return isPresent; + } + + public static ServicesInfo getServiceInfo(String elanInstanceName, long elanTag, String interfaceName) { + int priority = ElanConstants.ELAN_SERVICE_PRIORITY; + int instructionKey = 0; + List instructions = new ArrayList(); + instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(ElanUtils.getElanMetadataLabel(elanTag), MetaDataUtil.METADATA_MASK_SERVICE, ++instructionKey)); + instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(ElanConstants.ELAN_SMAC_TABLE, ++instructionKey)); + + ServicesInfo serviceInfo = InterfaceServiceUtil.buildServiceInfo(String.format("%s.%s", elanInstanceName, interfaceName), ElanConstants.ELAN_SERVICE_INDEX, + priority, ElanConstants.COOKIE_ELAN_INGRESS_TABLE, instructions); + return serviceInfo; + } + + public static void delete(DataBroker broker, LogicalDatastoreType datastoreType, + InstanceIdentifier path, FutureCallback callback) { + WriteTransaction tx = broker.newWriteOnlyTransaction(); + tx.delete(datastoreType, path); + Futures.addCallback(tx.submit(), callback); + } + + public static void syncWrite(DataBroker broker, LogicalDatastoreType datastoreType, + InstanceIdentifier path, T data) { + WriteTransaction tx = broker.newWriteOnlyTransaction(); + tx.put(datastoreType, path, data, true); + CheckedFuture futures = tx.submit(); + try { + futures.get(); + } catch (InterruptedException | ExecutionException e) { + logger.error("Error writing to datastore (path, data) : ({}, {})", path, data); + throw new RuntimeException(e.getMessage()); + } + } + + + public static BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority, + BigInteger cookie, List instructions) { + StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie).setFlowPriority(flowPriority).setInstruction(instructions); + return new BoundServicesBuilder().setKey(new BoundServicesKey(servicePriority)) + .setServiceName(serviceName).setServicePriority(servicePriority) + .setServiceType(ServiceTypeFlowBased.class).addAugmentation(StypeOpenflow.class, augBuilder.build()).build(); + } + + public static InstanceIdentifier buildServiceId(String vpnInterfaceName, short serviceIndex) { + return InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class, new ServicesInfoKey(vpnInterfaceName)) + .child(BoundServices.class, new BoundServicesKey(serviceIndex)).build(); + } + +} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/elanservice/impl/rev150216/ElanServiceImplModule.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/elanservice/impl/rev150216/ElanServiceImplModule.java new file mode 100644 index 00000000..ed10b25a --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/elanservice/impl/rev150216/ElanServiceImplModule.java @@ -0,0 +1,37 @@ +package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.elanservice.impl.rev150216; + +import org.opendaylight.vpnservice.elan.internal.ElanServiceProvider; +import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService; + +public class ElanServiceImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.elanservice.impl.rev150216.AbstractElanServiceImplModule { + public ElanServiceImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { + super(identifier, dependencyResolver); + } + + public ElanServiceImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.elanservice.impl.rev150216.ElanServiceImplModule oldModule, java.lang.AutoCloseable oldInstance) { + super(identifier, dependencyResolver, oldModule, oldInstance); + } + + @Override + public void customValidation() { + // add custom validation form module attributes here. + } + + @Override + public java.lang.AutoCloseable createInstance() { + RpcProviderRegistry rpcregistryDependency = getRpcregistryDependency(); + IdManagerService idManager = rpcregistryDependency.getRpcService(IdManagerService.class); + ElanServiceProvider provider = new ElanServiceProvider(rpcregistryDependency); + provider.setNotificationService(getNotificationServiceDependency()); + provider.setMdsalManager(getMdsalutilDependency()); + provider.setInterfaceManager(getOdlinterfaceDependency()); + provider.setInterfaceManagerRpcService(rpcregistryDependency.getRpcService(OdlInterfaceRpcService.class)); + provider.setItmManager(getItmmanagerDependency()); + provider.setIdManager(idManager); + getBrokerDependency().registerProvider(provider); + return provider; + } + +} diff --git a/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/elanservice/impl/rev150216/ElanServiceImplModuleFactory.java b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/elanservice/impl/rev150216/ElanServiceImplModuleFactory.java new file mode 100644 index 00000000..618f8c00 --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/elanservice/impl/rev150216/ElanServiceImplModuleFactory.java @@ -0,0 +1,13 @@ +/* +* Generated file +* +* Generated from: yang module name: elanservice-impl yang module local name: elanservice-impl +* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator +* Generated at: Fri Dec 04 18:32:00 IST 2015 +* +* Do not modify this file unless it is present under src/main directory +*/ +package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.elanservice.impl.rev150216; +public class ElanServiceImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.elanservice.impl.rev150216.AbstractElanServiceImplModuleFactory { + +} diff --git a/elanmanager/elanmanager-impl/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/elanmanager/elanmanager-impl/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 00000000..20a3ed25 --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/elanmanager/elanmanager-impl/src/main/yang/elanservice-impl.yang b/elanmanager/elanmanager-impl/src/main/yang/elanservice-impl.yang new file mode 100644 index 00000000..6af446e7 --- /dev/null +++ b/elanmanager/elanmanager-impl/src/main/yang/elanservice-impl.yang @@ -0,0 +1,81 @@ +module elanservice-impl { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:elanservice:impl"; + prefix "elanservice-impl"; + + import config { prefix config; revision-date 2013-04-05; } + import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;} + import opendaylight-sal-binding-broker-impl { prefix md-sal-binding-impl; revision-date 2013-10-28;} + import elanmanager-api { prefix elanmgr-api; revision-date 2015-07-07;} + import odl-mdsalutil { prefix odl-mdsal; revision-date 2015-04-10;} + import odl-interface {prefix odlif; revision-date 2015-03-31;} + import itm {prefix itm; revision-date 2015-07-01;} + + description + "Service definition for elanservice project"; + + revision "2015-02-16" { + description + "Initial revision"; + } + + identity elanservice-impl { + base config:module-type; + config:provided-service elanmgr-api:elanmanager-api; + config:java-name-prefix elanServiceImpl; + } + + augment "/config:modules/config:module/config:configuration" { + case elanservice-impl { + when "/config:modules/config:module/config:type = 'elanservice-impl'"; + container broker { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity md-sal-binding:binding-broker-osgi-registry; + } + } + } + container rpcregistry { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity md-sal-binding:binding-rpc-registry; + } + } + } + container mdsalutil { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity odl-mdsal:odl-mdsalutil; + } + } + } + container odlinterface { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity odlif:odl-interface; + } + } + } + container itmmanager { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity itm:itm; + } + } + } + container notification-service { + uses config:service-ref { + refine type { + mandatory true; + config:required-identity md-sal-binding-impl:binding-new-notification-service; + } + } + } + } + } +} \ No newline at end of file diff --git a/elanmanager/pom.xml b/elanmanager/pom.xml new file mode 100644 index 00000000..a34c56a5 --- /dev/null +++ b/elanmanager/pom.xml @@ -0,0 +1,49 @@ + + + + + + org.opendaylight.odlparent + odlparent + 1.6.0-SNAPSHOT + + + + org.opendaylight.vpnservice + elanmanager + 0.2.0-SNAPSHOT + elanmanager + pom + 4.0.0 + + 3.1.1 + + + elanmanager-api + elanmanager-impl + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + org.apache.maven.plugins + maven-install-plugin + + true + + + + + diff --git a/features/pom.xml b/features/pom.xml index 87365a79..a543c2de 100644 --- a/features/pom.xml +++ b/features/pom.xml @@ -34,6 +34,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL ${vpnservices.version} ${vpnservices.version} ${vpnservices.version} + ${vpnservices.version} ${vpnservices.version} ${vpnservices.version} ${vpnservices.version} @@ -185,6 +186,23 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL interfacemgr-api ${interfacemgr.version} + + ${project.groupId} + elanmanager-impl + ${elanmgr.version} + + + ${project.groupId} + elanmanager-impl + ${elanmgr.version} + config + xml + + + ${project.groupId} + elanmanager-api + ${elanmgr.version} + org.opendaylight.controller liblldp @@ -346,6 +364,14 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL libthrift 0.9.1 + + org.opendaylight.openflowplugin + features-openflowplugin-extension + features + ${openflowplugin.version} + xml + runtime + commons-net commons-net diff --git a/features/src/main/features/features.xml b/features/src/main/features/features.xml index 92e6865b..17f531cb 100644 --- a/features/src/main/features/features.xml +++ b/features/src/main/features/features.xml @@ -14,6 +14,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html mvn:org.opendaylight.controller/features-mdsal/${mdsal.version}/xml/features mvn:org.opendaylight.mdsal.model/features-mdsal-model/${mdsal.model.version}/xml/features mvn:org.opendaylight.openflowplugin/features-openflowplugin/${openflowplugin.version}/xml/features + mvn:org.opendaylight.openflowplugin/features-openflowplugin-extension/${openflowplugin.version}/xml/features mvn:org.opendaylight.netconf/features-restconf/${restconf.version}/xml/features mvn:org.opendaylight.ovsdb/features-ovsdb/${ovsdb.version}/xml/features mvn:org.opendaylight.neutron/features-neutron/${neutron.version}/xml/features @@ -21,6 +22,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html odl-mdsal-broker odl-mdsal-models odl-openflowplugin-nsf-model + odl-openflowplugin-nxm-extensions odl-ovsdb-southbound-impl-rest mvn:org.opendaylight.controller/liblldp/${liblldp.version} mvn:org.opendaylight.neutron/model/${neutron.version} @@ -60,6 +62,8 @@ and is available at http://www.eclipse.org/legal/epl-v10.html mvn:org.opendaylight.vpnservice/neutronvpn-impl/${neutronvpn.version} mvn:org.opendaylight.vpnservice/neutronvpn-shell/${neutronvpn.version} mvn:org.opendaylight.vpnservice/dhcpservice-impl/${vpnservices.version} + mvn:org.opendaylight.vpnservice/elanmanager-api/${elanmgr.version} + mvn:org.opendaylight.vpnservice/elanmanager-impl/${elanmgr.version} wrap:mvn:org.apache.thrift/libthrift/0.9.1$overwrite=merge&Bundle-Version=0.9.1&Export-Package=*;-noimport:=true;version="0.9.1" @@ -77,6 +81,8 @@ and is available at http://www.eclipse.org/legal/epl-v10.html mvn:org.opendaylight.vpnservice/itm-impl/${itm.version}/xml/config mvn:org.opendaylight.vpnservice/neutronvpn-impl/${neutronvpn.version}/xml/config mvn:org.opendaylight.vpnservice/dhcpservice-impl/${vpnservices.version}/xml/config + mvn:org.opendaylight.vpnservice/elanmanager-impl/${elanmgr.version}/xml/config + odl-vpnservice-impl diff --git a/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/exceptions/InterfaceAlreadyExistsException.java b/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/exceptions/InterfaceAlreadyExistsException.java new file mode 100644 index 00000000..16dda48c --- /dev/null +++ b/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/exceptions/InterfaceAlreadyExistsException.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.interfacemgr.exceptions; + +public class InterfaceAlreadyExistsException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public InterfaceAlreadyExistsException() { + + } + + public InterfaceAlreadyExistsException(String message) { + super(message); + } + +} diff --git a/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/exceptions/InterfaceNotFoundException.java b/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/exceptions/InterfaceNotFoundException.java new file mode 100644 index 00000000..ed46212d --- /dev/null +++ b/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/exceptions/InterfaceNotFoundException.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.interfacemgr.exceptions; + +public class InterfaceNotFoundException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public InterfaceNotFoundException() { + + } + + public InterfaceNotFoundException(String message) { + super(message); + } + +} diff --git a/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/exceptions/InterfaceServiceNotFoundException.java b/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/exceptions/InterfaceServiceNotFoundException.java new file mode 100644 index 00000000..13cdeb81 --- /dev/null +++ b/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/exceptions/InterfaceServiceNotFoundException.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.interfacemgr.exceptions; + +public class InterfaceServiceNotFoundException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public InterfaceServiceNotFoundException() { + } + + public InterfaceServiceNotFoundException(String message) { + super(message); + } +} diff --git a/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/globals/IfmConstants.java b/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/globals/IfmConstants.java new file mode 100644 index 00000000..85d1afcb --- /dev/null +++ b/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/globals/IfmConstants.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.interfacemgr.globals; + +import java.math.BigInteger; + +public class IfmConstants { + public static final String OF_URI_PREFIX = "openflow:"; + public static final String OF_URI_SEPARATOR = ":"; + public static final int DEFAULT_IFINDEX = 65536; + public static final int FLOW_HIGH_PRIORITY = 10; + public static final int FLOW_PRIORITY_FOR_UNTAGGED_VLAN = 4; + public static final int FLOW_TABLE_MISS_PRIORITY = 0; + public static final int DEFAULT_ARP_FLOW_PRIORITY = 100; + public static final int INVALID_PORT_NO = -1; + public static final BigInteger INVALID_DPID = new BigInteger("-1"); + //Id pool + public static final String IFM_IDPOOL_NAME = "interfaces"; + public static final long IFM_ID_POOL_START = 1L; + public static final long IFM_ID_POOL_END = 65535; + //Group Prefix + public static final long VLAN_GROUP_START = 1000; + public static final long TRUNK_GROUP_START = 20000; + public static final long LOGICAL_GROUP_START = 100000; + //Table + public static final short VLAN_INTERFACE_INGRESS_TABLE = 0; + public static final short VXLAN_TRUNK_INTERFACE_TABLE = 10; + public static final short TRUNK_L2_TABLE = 11; + public static final short GRE_TRUNK_INTERFACE_TABLE = 12; + public static final short LPORT_DISPATCHER_TABLE = 30; + public static final short L3_INTERFACE_TABLE = 80; + public static final long DELAY_TIME_IN_MILLISECOND = 10000; + //Cookies + public static final BigInteger COOKIE_VXLAN_TRUNK_L2_TABLE = new BigInteger("1200000", 16); + public static final BigInteger COOKIE_GRE_TRUNK_L2_TABLE = new BigInteger("1400000", 16); + public static final BigInteger COOKIE_L3_BASE = new BigInteger("8000000", 16); + //Tunnel Monitoring + public static final int DEFAULT_MONITOR_INTERVAL = 10000; +} diff --git a/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/globals/InterfaceInfo.java b/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/globals/InterfaceInfo.java new file mode 100644 index 00000000..0118fbf8 --- /dev/null +++ b/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/globals/InterfaceInfo.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.interfacemgr.globals; + +import java.io.Serializable; +import java.math.BigInteger; + +public class InterfaceInfo implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 1L; + + public enum InterfaceType { + VLAN_INTERFACE, + VXLAN_TRUNK_INTERFACE, + GRE_TRUNK_INTERFACE, + VXLAN_VNI_INTERFACE, + LOGICAL_GROUP_INTERFACE, + UNKNOWN_INTERFACE; + } + + public enum InterfaceAdminState { + ENABLED, + DISABLED + } + + public enum InterfaceOpState { + UP, + DOWN + } + + protected InterfaceType interfaceType; + protected int interfaceTag; + protected BigInteger dpId = IfmConstants.INVALID_DPID; + protected InterfaceAdminState adminState = InterfaceAdminState.ENABLED; + protected InterfaceOpState opState; + protected long groupId; + protected long l2domainGroupId; + protected int portNo = IfmConstants.INVALID_PORT_NO; + protected String portName; + protected String interfaceName; + protected boolean isUntaggedVlan; + + public String getInterfaceName() { + return interfaceName; + } + + public void setInterfaceName(String interfaceName) { + this.interfaceName = interfaceName; + } + + public InterfaceInfo(BigInteger dpId, String portName) { + this.dpId = dpId; + this.portName = portName; + } + + public InterfaceInfo(String portName) { + this.portName = portName; + } + + public boolean isOperational() { + return adminState == InterfaceAdminState.ENABLED && opState == InterfaceOpState.UP; + } + + public InterfaceType getInterfaceType() { + return interfaceType; + } + public void setInterfaceType(InterfaceType lportType) { + this.interfaceType = lportType; + } + public int getInterfaceTag() { + return interfaceTag; + } + public void setInterfaceTag(int interfaceTag) { + this.interfaceTag = interfaceTag; + } + public void setUntaggedVlan(boolean isUntaggedVlan) { + this.isUntaggedVlan = isUntaggedVlan; + } + public boolean isUntaggedVlan() { + return isUntaggedVlan; + } + public BigInteger getDpId() { + return dpId; + } + public void setDpId(BigInteger dpId) { + this.dpId = dpId; + } + public InterfaceAdminState getAdminState() { + return adminState; + } + public void setAdminState(InterfaceAdminState adminState) { + this.adminState = adminState; + } + public InterfaceOpState getOpState() { + return opState; + } + public void setOpState(InterfaceOpState opState) { + this.opState = opState; + } + public long getGroupId() { + return groupId; + } + public void setGroupId(long groupId) { + this.groupId = groupId; + } + public long getL2domainGroupId() { + return l2domainGroupId; + } + public void setL2domainGroupId(long l2domainGroupId) { + this.l2domainGroupId = l2domainGroupId; + } + + public int getPortNo() { + return portNo; + } + + public void setPortNo(int portNo) { + this.portNo = portNo; + } + + public void setPortName(String portName) { + this.portName = portName; + } + public String getPortName(){ + return this.portName; + } +} diff --git a/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/globals/InterfaceServiceUtil.java b/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/globals/InterfaceServiceUtil.java new file mode 100644 index 00000000..36f18989 --- /dev/null +++ b/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/globals/InterfaceServiceUtil.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.vpnservice.interfacemgr.globals; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.vpnservice.mdsalutil.FlowInfoKey; +import org.opendaylight.vpnservice.mdsalutil.GroupInfoKey; +import org.opendaylight.vpnservice.mdsalutil.MDSALUtil; +import org.opendaylight.vpnservice.mdsalutil.MatchFieldType; +import org.opendaylight.vpnservice.mdsalutil.MatchInfo; +import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.ServicesInfo; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.ServicesInfoBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.ServicesInfoKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServicesBuilder; + +import com.google.common.base.Optional; + +public class InterfaceServiceUtil { + + public static ServicesInfo buildServiceInfo(String serviceName, short serviceIndex, int servicePriority, + BigInteger cookie, List instructions) { + List boundService = new ArrayList(); + boundService.add(new BoundServicesBuilder().setServicePriority((short)servicePriority).setServiceName(serviceName).build()); + return new ServicesInfoBuilder().setBoundServices(boundService).setKey(new ServicesInfoKey(serviceName)).build(); + } + + public static ServicesInfo buildServiceInfo(String serviceName, short serviceIndex, int servicePriority, + BigInteger cookie) { + List boundService = new ArrayList(); + boundService.add(new BoundServicesBuilder().setServicePriority((short)servicePriority).setServiceName(serviceName).build()); + return new ServicesInfoBuilder().setBoundServices(boundService).setKey(new ServicesInfoKey(serviceName)).build(); + } + + public static List getMatchInfoForVlanLPort(BigInteger dpId, long portNo, long vlanId, boolean isVlanTransparent) { + List matches = new ArrayList(); + matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {dpId, BigInteger.valueOf(portNo)})); + if (vlanId != 0 && !isVlanTransparent) { + matches.add(new MatchInfo(MatchFieldType.vlan_vid, new long[] { vlanId })); + } + return matches; + } + + public static short getVlanId(String interfaceName, DataBroker broker) { + InstanceIdentifier id = InstanceIdentifier.builder(Interfaces.class) + .child(Interface.class, new InterfaceKey(interfaceName)).build(); + Optional ifInstance = MDSALUtil.read(LogicalDatastoreType.CONFIGURATION, id, broker); + if (ifInstance.isPresent()) { + IfL2vlan vlanIface =ifInstance.get().getAugmentation(IfL2vlan.class); + short vlanId = vlanIface.getVlanId() == null ? 0 : vlanIface.getVlanId().getValue().shortValue(); + return vlanId; + } + return -1; + } + + public static Set getStatRequestKeys(BigInteger dpId, short tableId, List matches, String flowId, long groupId) { + Set statRequestKeys = new HashSet(); + statRequestKeys.add(getFlowStatisticsKey(dpId, tableId, matches, flowId)); + statRequestKeys.add(getGroupStatisticsKey(dpId, groupId)); + return statRequestKeys; + } + + public static GroupInfoKey getGroupStatisticsKey(BigInteger dpId, long groupId) { + return new GroupInfoKey(dpId, groupId); + } + + public static FlowInfoKey getFlowStatisticsKey(BigInteger dpId, short tableId, List matches, String flowId) { + return new FlowInfoKey(dpId, tableId, MDSALUtil.buildMatches(matches), flowId); + } + + public static List getLPortDispatcherMatches(short serviceIndex, int interfaceTag) { + List mkMatches = new ArrayList(); + mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] { + MetaDataUtil.getMetaDataForLPortDispatcher(interfaceTag, serviceIndex), + MetaDataUtil.getMetaDataMaskForLPortDispatcher() })); + return mkMatches; + } + +} diff --git a/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/globals/LogicalGroupInterfaceInfo.java b/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/globals/LogicalGroupInterfaceInfo.java new file mode 100644 index 00000000..c8206d08 --- /dev/null +++ b/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/globals/LogicalGroupInterfaceInfo.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.interfacemgr.globals; + +import java.math.BigInteger; +import java.net.InetAddress; +import java.util.*; + +import org.opendaylight.vpnservice.mdsalutil.ActionInfo; +import org.opendaylight.vpnservice.mdsalutil.InstructionInfo; +import org.opendaylight.vpnservice.mdsalutil.MatchInfo; + +public class LogicalGroupInterfaceInfo extends InterfaceInfo { + + /* + List of vxlan/GRE physical tunnel interfaces makes a logical tunnel interface + between a pair of DPNs + + */ + + private List parentInterfaceNames; + + public LogicalGroupInterfaceInfo(String portName, BigInteger srcDpId,List pInterfaces) { + super(srcDpId,portName); + + parentInterfaceNames = new ArrayList(pInterfaces); + } + + public List getParentInterfaceNames() { + return parentInterfaceNames; + } + + public void addParentInterfaceName(String parentIfname) { + parentInterfaceNames.add(parentIfname); + } + + public int getTotalParentInterfaces() { + return parentInterfaceNames.size(); + } + + public void deleteParentInterfaceName(String parentIfname) { + parentInterfaceNames.remove(parentIfname); + } + +} + +/*--------------------------------*/ + diff --git a/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/globals/VlanInterfaceInfo.java b/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/globals/VlanInterfaceInfo.java new file mode 100644 index 00000000..77ad4c80 --- /dev/null +++ b/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/globals/VlanInterfaceInfo.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.interfacemgr.globals; + +import java.math.BigInteger; + +public class VlanInterfaceInfo extends InterfaceInfo { + + /** + * + */ + private static final long serialVersionUID = 1L; + private short vlanId; + private boolean isVlanTransparent; + + public VlanInterfaceInfo(BigInteger dpId, + String portName, short vlanId) { + super(dpId, portName); + this.vlanId = vlanId; + } + + public VlanInterfaceInfo(String portName, short vlanId) { + super(portName); + this.vlanId = vlanId; + } + + public short getVlanId() { + return vlanId; + } + + public void setVlanId(short vlanId) { + this.vlanId = vlanId; + } + + public boolean isVlanTransparent() { + return isVlanTransparent; + } + + public void setVlanTransparent(boolean isVlanTransparent) { + this.isVlanTransparent = isVlanTransparent; + } +} diff --git a/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/interfaces/IInterfaceManager.java b/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/interfaces/IInterfaceManager.java index f3ba03d3..c79b1d25 100644 --- a/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/interfaces/IInterfaceManager.java +++ b/interfacemgr/interfacemgr-api/src/main/java/org/opendaylight/vpnservice/interfacemgr/interfaces/IInterfaceManager.java @@ -8,12 +8,12 @@ package org.opendaylight.vpnservice.interfacemgr.interfaces; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; - import java.math.BigInteger; import java.util.List; + +import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo; import org.opendaylight.vpnservice.mdsalutil.ActionInfo; -import org.opendaylight.vpnservice.mdsalutil.MatchInfo; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; @Deprecated public interface IInterfaceManager { @@ -34,4 +34,8 @@ public interface IInterfaceManager { @Deprecated public Long getPortForInterface(Interface intf); + + public InterfaceInfo getInterfaceInfo(String intInfo); + + public InterfaceInfo getInterfaceInfoFromOperationalDataStore(String interfaceName, InterfaceInfo.InterfaceType interfaceType); } \ No newline at end of file diff --git a/interfacemgr/interfacemgr-api/src/main/yang/interface-statistics.yang b/interfacemgr/interfacemgr-api/src/main/yang/interface-statistics.yang new file mode 100644 index 00000000..9b4c856e --- /dev/null +++ b/interfacemgr/interfacemgr-api/src/main/yang/interface-statistics.yang @@ -0,0 +1,58 @@ +module interface-statistics { + namespace "urn:opendaylight:vpnservice:interface:statistics"; + prefix if-stats; + + import ietf-interfaces { + prefix if; + } + + revision "2015-08-24" { + description "YANG model describes rpc to retrieve the different ingress/egress statistics ie. packet/byte counts"; + } + + typedef result-code { + type enumeration { + enum not-found; + enum success; + enum incomplete; + } + } + + grouping service-enitity-statistics { + leaf packet-tx-count { + type uint32; + } + leaf packet-rx-count { + type uint32; + } + leaf byte-tx-count { + type uint32; + } + leaf byte-rx-count { + type uint32; + } + } + + grouping stat-reply { + leaf stat-result-code { + type result-code; + } + uses service-enitity-statistics; + } + + rpc get-interface-statistics { + input { + leaf interface-name { + type leafref { + path "/if:interfaces/if:interface/if:name"; + } + } + } + output { + container stat-result { + uses stat-reply; + } + } + } + +} diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmConstants.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmConstants.java index 2e573bef..927f8aeb 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmConstants.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmConstants.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, @@ -20,7 +20,15 @@ public class IfmConstants { public static final int DEFAULT_IFINDEX = 65536; public static final int DEFAULT_FLOW_PRIORITY = 5; public static final String IFM_LPORT_TAG_IDPOOL_NAME = "vlaninterfaces.lporttag"; - public static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000002", 16);; + public static final short VLAN_INTERFACE_INGRESS_TABLE = 0; + //Group Prefix + public static final long VLAN_GROUP_START = 1000; + public static final long TRUNK_GROUP_START = 20000; + public static final long LOGICAL_GROUP_START = 100000; + public static final short INTERNAL_TUNNEL_TABLE = 22; + public static final short EXTERNAL_TUNNEL_TABLE = 23; + public static final short LFIB_TABLE = 20; + public static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000002", 16); public static final String TUNNEL_TABLE_FLOWID_PREFIX = "TUNNEL."; public static final BigInteger TUNNEL_TABLE_COOKIE = new BigInteger("9000000", 16); } diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmUtil.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmUtil.java index 44f754e8..adebb5fa 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmUtil.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, @@ -14,9 +14,15 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import com.google.common.base.Optional; + import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo; +import org.opendaylight.vpnservice.interfacemgr.globals.VlanInterfaceInfo; +import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; @@ -26,6 +32,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeBase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeGre; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathId; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInputBuilder; @@ -36,6 +45,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPool; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan.L2vlanMode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; @@ -105,6 +117,17 @@ public class IfmUtil { return strList; } + public static long getGroupId(long ifIndex, InterfaceInfo.InterfaceType infType) { + if (infType == InterfaceInfo.InterfaceType.LOGICAL_GROUP_INTERFACE) { + return ifIndex + IfmConstants.LOGICAL_GROUP_START; + } + else if (infType == InterfaceInfo.InterfaceType.VLAN_INTERFACE) { + return ifIndex + IfmConstants.VLAN_GROUP_START; + } else { + return ifIndex + IfmConstants.TRUNK_GROUP_START; + } + } + public static List getDpIdPortNameAndSuffixFromInterfaceName(String intfName) { List strList = new ArrayList<>(3); int index1 = intfName.indexOf(":"); @@ -200,4 +223,57 @@ public class IfmUtil { } return null; } + + public static NodeConnectorId getNodeConnectorIdFromInterface(Interface iface, DataBroker dataBroker) { + return FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker); + } + + public static InterfaceInfo.InterfaceType getInterfaceType(Interface iface) { + InterfaceInfo.InterfaceType interfaceType = + org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo.InterfaceType.UNKNOWN_INTERFACE; + Class ifType = iface.getType(); + + if (ifType.isAssignableFrom(L2vlan.class)) { + interfaceType = org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo.InterfaceType.VLAN_INTERFACE; + } else if (ifType.isAssignableFrom(Tunnel.class)) { + IfTunnel ifTunnel = iface.getAugmentation(IfTunnel.class); + Class tunnelType = ifTunnel.getTunnelInterfaceType(); + if (tunnelType.isAssignableFrom(TunnelTypeVxlan.class)) { + interfaceType = InterfaceInfo.InterfaceType.VXLAN_TRUNK_INTERFACE; + } else if (tunnelType.isAssignableFrom(TunnelTypeGre.class)) { + interfaceType = InterfaceInfo.InterfaceType.GRE_TRUNK_INTERFACE; + } + } + // TODO: Check if the below condition is still needed/valid + //else if (ifType.isAssignableFrom(InterfaceGroup.class)) { + // interfaceType = org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo.InterfaceType.LOGICAL_GROUP_INTERFACE; + //} + return interfaceType; + } + + public static VlanInterfaceInfo getVlanInterfaceInfo(String interfaceName, Interface iface, BigInteger dpId){ + IfL2vlan vlanIface = iface.getAugmentation(IfL2vlan.class); + + short vlanId = 0; + //FIXME :Use this below thing properly + VlanInterfaceInfo vlanInterfaceInfo = new VlanInterfaceInfo(dpId, "someString", vlanId); + + if (vlanIface != null) { + vlanId = vlanIface.getVlanId() == null ? 0 : vlanIface.getVlanId().getValue().shortValue(); + L2vlanMode l2VlanMode = vlanIface.getL2vlanMode(); + + if (l2VlanMode == L2vlanMode.Transparent) { + vlanInterfaceInfo.setVlanTransparent(true); + } + if (l2VlanMode == L2vlanMode.NativeUntagged) { + vlanInterfaceInfo.setUntaggedVlan(true); + } + vlanInterfaceInfo.setVlanId(vlanId); + + } + return vlanInterfaceInfo; + } + + + } diff --git a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfacemgrProvider.java b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfacemgrProvider.java index 46fccb11..f1a9c849 100644 --- a/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfacemgrProvider.java +++ b/interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfacemgrProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, @@ -7,38 +7,52 @@ */ package org.opendaylight.vpnservice.interfacemgr; +import java.math.BigInteger; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext; import org.opendaylight.controller.sal.binding.api.BindingAwareProvider; import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry; +import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils; +import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo; +import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo.InterfaceAdminState; +import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager; import org.opendaylight.vpnservice.interfacemgr.listeners.InterfaceConfigListener; import org.opendaylight.vpnservice.interfacemgr.listeners.InterfaceInventoryStateListener; import org.opendaylight.vpnservice.interfacemgr.listeners.InterfaceTopologyStateListener; -import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager; +import org.opendaylight.vpnservice.interfacemgr.listeners.VlanMemberConfigListener; import org.opendaylight.vpnservice.interfacemgr.rpcservice.InterfaceManagerRpcService; import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.listeners.FlowBasedServicesConfigListener; import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.listeners.FlowBasedServicesInterfaceStateListener; -import org.opendaylight.vpnservice.interfacemgr.listeners.VlanMemberConfigListener; import org.opendaylight.vpnservice.mdsalutil.ActionInfo; -import org.opendaylight.vpnservice.mdsalutil.MatchInfo; import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService; -import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.*; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEndpointIpForDpnInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEndpointIpForDpnInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEndpointIpForDpnOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetPortFromInterfaceInput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetPortFromInterfaceInputBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetPortFromInterfaceOutput; +import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService; import org.opendaylight.yangtools.yang.common.RpcResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.math.BigInteger; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; - public class InterfacemgrProvider implements BindingAwareProvider, AutoCloseable, IInterfaceManager { private static final Logger LOG = LoggerFactory.getLogger(InterfacemgrProvider.class); @@ -52,7 +66,7 @@ public class InterfacemgrProvider implements BindingAwareProvider, AutoCloseable private FlowBasedServicesInterfaceStateListener flowBasedServicesInterfaceStateListener; private FlowBasedServicesConfigListener flowBasedServicesConfigListener; private VlanMemberConfigListener vlanMemberConfigListener; - + private DataBroker dataBroker; private InterfaceManagerRpcService interfaceManagerRpcService; private BindingAwareBroker.RpcRegistration rpcRegistration; @@ -68,7 +82,7 @@ public class InterfacemgrProvider implements BindingAwareProvider, AutoCloseable public void onSessionInitiated(ProviderContext session) { LOG.info("InterfacemgrProvider Session Initiated"); try { - final DataBroker dataBroker = session.getSALService(DataBroker.class); + dataBroker = session.getSALService(DataBroker.class); idManager = rpcProviderRegistry.getRpcService(IdManagerService.class); createIdPool(); @@ -158,6 +172,89 @@ public class InterfacemgrProvider implements BindingAwareProvider, AutoCloseable return null; } + @Override + public InterfaceInfo getInterfaceInfo(String interfaceName) { + //FIXME [ELANBE] This is not working yet, fix this + + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface + ifState = InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceName,dataBroker); + + if(ifState == null){ + LOG.error("Interface {} is not present", interfaceName); + return null; + } + + Integer lportTag = ifState.getIfIndex(); + Interface intf = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(interfaceName), dataBroker); + + NodeConnectorId ncId = IfmUtil.getNodeConnectorIdFromInterface(intf, dataBroker); + InterfaceInfo.InterfaceType interfaceType = IfmUtil.getInterfaceType(intf); + InterfaceInfo interfaceInfo = null; + BigInteger dpId = org.opendaylight.vpnservice.interfacemgr.globals.IfmConstants.INVALID_DPID; + Integer portNo = org.opendaylight.vpnservice.interfacemgr.globals.IfmConstants.INVALID_PORT_NO; + if (ncId !=null ) { + dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(ncId)); + portNo = Integer.parseInt(IfmUtil.getPortNoFromNodeConnectorId(ncId)); + } + + if(interfaceType == InterfaceInfo.InterfaceType.VLAN_INTERFACE){ + interfaceInfo = IfmUtil.getVlanInterfaceInfo(interfaceName, intf, dpId); + } else if (interfaceType == InterfaceInfo.InterfaceType.VXLAN_TRUNK_INTERFACE || interfaceType == InterfaceInfo.InterfaceType.GRE_TRUNK_INTERFACE) {/* + trunkInterfaceInfo trunkInterfaceInfo = (TrunkInterfaceInfo) ConfigIfmUtil.getTrunkInterfaceInfo(ifName, ConfigIfmUtil.getInterfaceByIfName(dataBroker, ifName)); + String higherLayerIf = inf.getHigherLayerIf().get(0); + Interface vlanInterface = ConfigIfmUtil.getInterfaceByIfName(dataBroker, higherLayerIf); + trunkInterfaceInfo.setPortName(vlanInterface.getAugmentation(BaseConfig.class).getParentInterface()); + trunkInterfaceManager.updateTargetMacAddressInInterfaceInfo(trunkInterfaceInfo, trunkInterface); + if (trunkInterface.getPhysAddress() != null) { + trunkInterfaceInfo.setLocalMacAddress(trunkInterface.getPhysAddress().getValue()); + } + interfaceInfo = trunkInterfaceInfo; + interfaceInfo.setL2domainGroupId(IfmUtil.getGroupId(OperationalIfmUtil.getInterfaceStateByIfName(dataBroker, higherLayerIf).getIfIndex(), InterfaceType.VLAN_INTERFACE)); + */} else { + LOG.error("Type of Interface {} is unknown", interfaceName); + return null; + } + interfaceInfo.setDpId(dpId); + interfaceInfo.setPortNo(portNo); + interfaceInfo.setAdminState((intf.isEnabled() == true) ? InterfaceAdminState.ENABLED : InterfaceAdminState.DISABLED); + interfaceInfo.setInterfaceName(interfaceName); + interfaceInfo.setInterfaceTag(lportTag); + interfaceInfo.setInterfaceType(interfaceType); + interfaceInfo.setGroupId(IfmUtil.getGroupId(lportTag, interfaceType)); + interfaceInfo.setOpState((ifState.getOperStatus() == OperStatus.Up) ? InterfaceInfo.InterfaceOpState.UP : InterfaceInfo.InterfaceOpState.DOWN); + + + return interfaceInfo; + + } + + @Override + public InterfaceInfo getInterfaceInfoFromOperationalDataStore(String interfaceName, InterfaceInfo.InterfaceType interfaceType) { + InterfaceInfo interfaceInfo = new InterfaceInfo(interfaceName); + org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState = InterfaceManagerCommonUtils + .getInterfaceStateFromOperDS(interfaceName, dataBroker); + if (ifState == null) { + LOG.error("Interface {} is not present", interfaceName); + return null; + } + Integer lportTag = ifState.getIfIndex(); + Interface intf = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(interfaceName), dataBroker); + NodeConnectorId ncId = IfmUtil.getNodeConnectorIdFromInterface(intf, dataBroker); + if (ncId != null) { + interfaceInfo.setDpId(new BigInteger(IfmUtil.getDpnFromNodeConnectorId(ncId))); + interfaceInfo.setPortNo(Integer.parseInt(IfmUtil.getPortNoFromNodeConnectorId(ncId))); + } + interfaceInfo.setAdminState((intf.isEnabled() == true) ? InterfaceAdminState.ENABLED : InterfaceAdminState.DISABLED); + interfaceInfo.setInterfaceName(interfaceName); + interfaceInfo.setInterfaceTag(lportTag); + interfaceInfo.setInterfaceType(interfaceType); + interfaceInfo.setGroupId(IfmUtil.getGroupId(lportTag, interfaceType)); + interfaceInfo.setOpState((ifState.getOperStatus() == OperStatus.Up) ? InterfaceInfo.InterfaceOpState.UP : InterfaceInfo.InterfaceOpState.DOWN); + + + return interfaceInfo; + } + @Override public BigInteger getDpnForInterface(String ifName) { GetDpidFromInterfaceInput input = new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build(); diff --git a/itm/itm-api/src/main/java/org/opendaylight/vpnservice/itm/globals/ITMConstants.java b/itm/itm-api/src/main/java/org/opendaylight/vpnservice/itm/globals/ITMConstants.java index 88cf81df..eddaeb4f 100644 --- a/itm/itm-api/src/main/java/org/opendaylight/vpnservice/itm/globals/ITMConstants.java +++ b/itm/itm-api/src/main/java/org/opendaylight/vpnservice/itm/globals/ITMConstants.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, @@ -10,11 +10,16 @@ package org.opendaylight.vpnservice.itm.globals; import java.math.BigInteger; + public class ITMConstants{ public static final BigInteger COOKIE_ITM = new BigInteger("9000000", 16); public static final String ITM_IDPOOL_NAME = "Itmservices"; public static final long ITM_IDPOOL_START = 1L; public static final String ITM_IDPOOL_SIZE = "100000"; + public static final short INTERNAL_TUNNEL_TABLE = 22; + + + public static final short TERMINATING_SERVICE_TABLE = 36; } diff --git a/mdsalutil/mdsalutil-api/pom.xml b/mdsalutil/mdsalutil-api/pom.xml index 424319fa..a32f3cde 100644 --- a/mdsalutil/mdsalutil-api/pom.xml +++ b/mdsalutil/mdsalutil-api/pom.xml @@ -31,5 +31,16 @@ liblldp ${liblldp.version} + + org.opendaylight.openflowplugin + openflowplugin-extension-nicira + ${openflowplugin.version} + + + org.opendaylight.openflowplugin + openflowjava-extension-nicira + ${openflowplugin.version} + + diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/ActionType.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/ActionType.java old mode 100644 new mode 100755 index 847284f5..19ec9da2 --- a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/ActionType.java +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/ActionType.java @@ -10,11 +10,6 @@ package org.opendaylight.vpnservice.mdsalutil; import java.math.BigInteger; import java.net.InetAddress; -//import org.opendaylight.yang.gen.v1.urn.ericsson.experimenter.action.types.rev140228.EricFilterTypes; -//import org.opendaylight.yang.gen.v1.urn.ericsson.experimenter.action.types.rev140228.action.types.action.action.ExperimenterActionTypeBuilder; -//import org.opendaylight.yang.gen.v1.urn.ericsson.experimenter.action.types.rev140228.action.types.action.action.experimenter.action.type.action.type.FilterTypesActionBuilder; -//import org.opendaylight.yang.gen.v1.urn.ericsson.experimenter.action.types.rev140228.filter.types.group.Metadata; -//import org.opendaylight.yang.gen.v1.urn.ericsson.experimenter.action.types.rev140228.filter.types.group.MetadataBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCaseBuilder; @@ -34,12 +29,14 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.mpls.action._case.PushMplsActionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.pbb.action._case.PushPbbActionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.push.vlan.action._case.PushVlanActionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetField; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetFieldBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.OutputPortValues; -//import org.opendaylight.yang.gen.v1.urn.ericsson.experimenter.flow.types.rev140422.EricssonPortTypes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ApplyActionsCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActions; import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder; @@ -62,15 +59,24 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder; -//import org.opendaylight.yang.gen.v1.urn.ericsson.experimenter.action.types.rev140228.action.types.action.action.ExperimenterActionTypeBuilder; -//import org.opendaylight.yang.gen.v1.urn.ericsson.experimenter.action.types.rev140228.action.types.action.action.experimenter.action.type.action.type.VxlanPopActionBuilder; -//import org.opendaylight.yang.gen.v1.urn.ericsson.experimenter.action.types.rev140228.action.types.action.action.experimenter.action.type.action.type.VxlanPushActionBuilder; -//import org.opendaylight.yang.gen.v1.urn.ericsson.experimenter.action.types.rev140228.action.types.action.action.experimenter.action.type.action.type.GrePopActionBuilder; -//import org.opendaylight.yang.gen.v1.urn.ericsson.experimenter.action.types.rev140228.action.types.action.action.experimenter.action.type.action.type.GrePushActionBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropAction; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.drop.action._case.DropActionBuilder; - +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.action.rev150203.action.grouping.action.choice.set.field._case.SetFieldActionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.OfjNxActionOutputRegGrouping; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.action.rev140421.action.container.action.choice.ActionOutputRegBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.group.input.buckets.bucket.action.action.NxActionOutputRegRpcAddGroupCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.group.input.buckets.bucket.action.action.NxActionOutputRegRpcAddGroupCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.add.group.input.buckets.bucket.action.action.NxActionResubmitRpcAddGroupCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionOutputRegNodesNodeGroupBucketsBucketActionsCase; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionOutputRegNodesNodeGroupBucketsBucketActionsCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.group.buckets.bucket.action.action.NxActionRegLoadNodesNodeGroupBucketsBucketActionsCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nodes.node.table.flow.instructions.instruction.instruction.apply.actions._case.apply.actions.action.action.NxActionOutputRegNodesNodeTableFlowApplyActionsCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.output.reg.grouping.NxOutputReg; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.output.reg.grouping.NxOutputRegBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.resubmit.grouping.NxResubmitBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.src.choice.grouping.src.choice.SrcNxRegCaseBuilder; public enum ActionType { group { @Override @@ -372,6 +378,7 @@ public enum ActionType { } }, + drop_action { @Override @@ -380,9 +387,44 @@ public enum ActionType { DropAction dropAction = dab.build(); ActionBuilder ab = new ActionBuilder(); ab.setAction(new DropActionCaseBuilder().setDropAction(dropAction).build()); + ab.setKey(new ActionKey(actionInfo.getActionKey())).build(); + return ab.build(); + } + }, + set_field_reg { + + @Override + public Action buildAction(ActionInfo actionInfo) { + ActionBuilder ab = new ActionBuilder(); + String[] actionValues = actionInfo.getActionValues(); + NxOutputReg r = new NxOutputRegBuilder().setSrc( + new org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.action.rev140714.nx.action.output.reg.grouping.nx.output.reg.SrcBuilder().setSrcChoice( + new SrcNxRegCaseBuilder().setNxReg(NxmNxReg1.class).build()) + .setOfsNbits(Integer.valueOf(Integer.parseInt(actionValues[0]))) + .build()) + .setMaxLen(Integer.valueOf(0xffff)) + .build(); + ab.setAction(new NxActionOutputRegNodesNodeGroupBucketsBucketActionsCaseBuilder().setNxOutputReg(r).build()); + ab.setKey(new ActionKey(actionInfo.getActionKey())); return ab.build(); } }, + + + + nx_resubmit { + + @Override + public Action buildAction(ActionInfo actionInfo) { + NxResubmitBuilder nxarsb = new NxResubmitBuilder(); + nxarsb.setTable((short) 55); + ActionBuilder ab = new ActionBuilder(); + ab.setAction(new NxActionResubmitRpcAddGroupCaseBuilder().setNxResubmit(nxarsb.build()).build()); + ab.setKey(new ActionKey(actionInfo.getActionKey())); + return ab.build(); + } + }, + goto_table { @Override diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/FlowInfoKey.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/FlowInfoKey.java new file mode 100644 index 00000000..b6229802 --- /dev/null +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/FlowInfoKey.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.mdsalutil; + +import java.math.BigInteger; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match; + +public final class FlowInfoKey { + + private final BigInteger dpId; + private final short tableId; + private final Match matches; + private final String flowId; + + public FlowInfoKey(BigInteger dpId, short tableId, Match matches, String flowId) { + this.dpId = dpId; + this.tableId = tableId; + this.matches = matches; + this.flowId = flowId; + } + + public short getTableId() { + return tableId; + } + + public Match getMatches() { + return matches; + } + + public BigInteger getDpId() { + return dpId; + } + + public String getFlowId() { + return flowId; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((dpId == null) ? 0 : dpId.hashCode()); + result = prime * result + ((matches == null) ? 0 : matches.hashCode()); + result = prime * result + tableId; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + FlowInfoKey other = (FlowInfoKey) obj; + if (dpId == null) { + if (other.dpId != null) + return false; + } else if (!dpId.equals(other.dpId)) + return false; + if (matches == null) { + if (other.matches != null) + return false; + } else if (!matches.equals(other.matches)) + return false; + if (tableId != other.tableId) + return false; + return true; + } + + @Override + public String toString() { + return "FlowStatisticsKey [dpId=" + dpId + ", tableId=" + tableId + ", matches=" + matches + "]"; + } + +} diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/GroupInfoKey.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/GroupInfoKey.java new file mode 100644 index 00000000..e31ff5fd --- /dev/null +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/GroupInfoKey.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.mdsalutil; + +import java.math.BigInteger; + +public final class GroupInfoKey { + + private final BigInteger dpId; + private final long groupId; + + public GroupInfoKey(BigInteger dpId, long groupId) { + this.dpId = dpId; + this.groupId = groupId; + } + + public long getGroupId() { + return groupId; + } + + public BigInteger getDpId() { + return dpId; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((dpId == null) ? 0 : dpId.hashCode()); + result = prime * result + (int) (groupId ^ (groupId >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + GroupInfoKey other = (GroupInfoKey) obj; + if (dpId == null) { + if (other.dpId != null) + return false; + } else if (!dpId.equals(other.dpId)) + return false; + if (groupId != other.groupId) + return false; + return true; + } + + @Override + public String toString() { + return "GroupStatisticsKey [dpId=" + dpId + ", groupId=" + groupId + "]"; + } + +} diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MDSALUtil.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MDSALUtil.java index 41e66bfc..27afd5c3 100644 --- a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MDSALUtil.java +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MDSALUtil.java @@ -246,7 +246,7 @@ public class MDSALUtil { return EMPTY_Instructions; } - protected static Match buildMatches(List listMatchInfo) { + public static Match buildMatches(List listMatchInfo) { if (listMatchInfo != null) { MatchBuilder matchBuilder = new MatchBuilder(); Map, Object> mapMatchBuilder = new HashMap, Object>(); diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MatchFieldType.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MatchFieldType.java old mode 100644 new mode 100755 index 57a7f38d..e514e3eb --- a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MatchFieldType.java +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MatchFieldType.java @@ -8,6 +8,8 @@ package org.opendaylight.vpnservice.mdsalutil; import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix; @@ -31,6 +33,16 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.protocol.match.fields.PbbBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg1; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlowBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.grouping.ExtensionBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionListBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNodesNodeTableFlow; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxAugMatchNodesNodeTableFlowBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.NxmNxReg1Key; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.nicira.match.rev140714.nxm.nx.reg.grouping.NxmNxRegBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.ArpOp; import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.ArpSpa; import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.ArpTpa; @@ -576,6 +588,39 @@ public enum MatchFieldType { }, + reg1 { + @Override + protected Class getMatchType() { + return MatchField.class; + } + + @Override + public void createInnerMatchBuilder(MatchInfo matchInfo, Map, Object> mapMatchBuilder) { + NxmNxRegBuilder regdataBuilder = (NxmNxRegBuilder) mapMatchBuilder.get(NxmNxRegBuilder.class); + if (regdataBuilder == null) { + regdataBuilder = new NxmNxRegBuilder(); + mapMatchBuilder.put(NxmNxRegBuilder.class, regdataBuilder); + } + long[] metadataValues = matchInfo.getMatchValues(); + regdataBuilder.setValue(metadataValues[0]).build(); + ArrayList extensions = new ArrayList<>(); + NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxReg(new NxmNxRegBuilder().setReg(NxmNxReg1.class).setValue(metadataValues[0]).build()).build(); + extensions.add(new ExtensionListBuilder().setExtensionKey(NxmNxReg1Key.class).setExtension(new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build()).build()); + GeneralAugMatchNodesNodeTableFlow m = new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(extensions).build(); + } + + @Override + public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map, Object> mapMatchBuilder) { + List extensions = new ArrayList<>(); + long[] matchvalues = matchInfo.getMatchValues(); + NxAugMatchNodesNodeTableFlow am = new NxAugMatchNodesNodeTableFlowBuilder().setNxmNxReg(new NxmNxRegBuilder().setReg(NxmNxReg1.class).setValue(matchvalues[0]).build()).build(); + extensions.add(new ExtensionListBuilder().setExtensionKey(NxmNxReg1Key.class).setExtension(new ExtensionBuilder().addAugmentation(NxAugMatchNodesNodeTableFlow.class, am).build()).build()); + GeneralAugMatchNodesNodeTableFlow m = new GeneralAugMatchNodesNodeTableFlowBuilder().setExtensionList(extensions).build(); + matchBuilderInOut.addAugmentation(GeneralAugMatchNodesNodeTableFlow.class, m); + + } + }, + vlan_vid { @Override protected Class getMatchType() { diff --git a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/interfaces/IMdsalApiManager.java b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/interfaces/IMdsalApiManager.java index defa0f59..3535c435 100644 --- a/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/interfaces/IMdsalApiManager.java +++ b/mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/interfaces/IMdsalApiManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, @@ -16,6 +16,7 @@ import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFaile import org.opendaylight.vpnservice.mdsalutil.ActionInfo; import org.opendaylight.vpnservice.mdsalutil.FlowEntity; import org.opendaylight.vpnservice.mdsalutil.GroupEntity; +import org.opendaylight.vpnservice.mdsalutil.*; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow; public interface IMdsalApiManager { @@ -44,4 +45,29 @@ public interface IMdsalApiManager { public void sendARPPacketOutWithActions(BigInteger dpnId, byte[] payload, List action_info); + /** + * API to remove the flow on Data Plane Node synchronously. It internally waits for + * Flow Change Notification to confirm flow delete request is being sent with-in delayTime. + * + * @param flowEntity + * @param delayTime + */ + public void syncRemoveFlow(FlowEntity flowEntity, long delayTime); + + /** + * API to install the Group on Data Plane Node synchronously. It internally waits for + * Group Change Notification to confirm group mod request is being sent with-in delayTime + * + * @param groupEntity + * @param delayTime + */ + public void syncInstallGroup(GroupEntity groupEntity, long delayTime); + + /** + * API to remove the Group on Data Plane Node synchronously. It internally waits for + * Group Change Notification to confirm group delete request is being sent. + * + * @param groupEntity + */ + public void syncRemoveGroup(GroupEntity groupEntity); } diff --git a/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALManager.java b/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALManager.java index defe0226..9c2915a0 100644 --- a/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALManager.java +++ b/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, @@ -11,11 +11,15 @@ package org.opendaylight.vpnservice.mdsalutil.internal; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + import org.opendaylight.vpnservice.mdsalutil.ActionInfo; import org.opendaylight.vpnservice.mdsalutil.ActionType; import org.opendaylight.vpnservice.mdsalutil.FlowEntity; import org.opendaylight.vpnservice.mdsalutil.GroupEntity; import org.opendaylight.vpnservice.mdsalutil.MDSALUtil; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table; @@ -40,6 +44,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.opendaylight.vpnservice.mdsalutil.*; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException; @@ -57,6 +62,8 @@ public class MDSALManager implements AutoCloseable { private DataBroker m_dataBroker; private PacketProcessingService m_packetProcessingService; + private ConcurrentMap flowMap = new ConcurrentHashMap(); + private ConcurrentMap groupMap = new ConcurrentHashMap (); /** * Writes the flows and Groups to the MD SAL DataStore @@ -324,4 +331,64 @@ public class MDSALManager implements AutoCloseable { return nodeDpn; } + public void syncSetUpFlow(FlowEntity flowEntity, long delay, boolean isRemove) { + s_logger.trace("syncSetUpFlow for flowEntity {} ", flowEntity); + if (flowEntity.getCookie() == null) { + flowEntity.setCookie(new BigInteger("0110000", 16)); + } + Flow flow = flowEntity.getFlowBuilder().build(); + String flowId = flowEntity.getFlowId(); + BigInteger dpId = flowEntity.getDpnId(); + short tableId = flowEntity.getTableId(); + Match matches = flow.getMatch(); + FlowKey flowKey = new FlowKey( new FlowId(flowId)); + Node nodeDpn = buildDpnNode(dpId); + InstanceIdentifier flowInstanceId = InstanceIdentifier.builder(Nodes.class) + .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class) + .child(Table.class, new TableKey(flow.getTableId())).child(Flow.class, flowKey).build(); + Runnable notifyTask = new NotifyTask(); + FlowInfoKey flowInfoKey = new FlowInfoKey(dpId, tableId, matches, flowId); + synchronized (flowInfoKey.toString().intern()) { + flowMap.put(flowInfoKey, notifyTask); + if (isRemove) { + MDSALUtil.syncDelete(m_dataBroker, LogicalDatastoreType.CONFIGURATION, flowInstanceId); + } else { + MDSALUtil.syncWrite(m_dataBroker, LogicalDatastoreType.CONFIGURATION, flowInstanceId, flow); + } + synchronized (notifyTask) { + try { + notifyTask.wait(delay); + } catch (InterruptedException e){} + } + } + } + + public void syncSetUpGroup(GroupEntity groupEntity, long delayTime, boolean isRemove) { + s_logger.trace("syncSetUpGroup for groupEntity {} ", groupEntity); + Group group = groupEntity.getGroupBuilder().build(); + BigInteger dpId = groupEntity.getDpnId(); + Node nodeDpn = buildDpnNode(dpId); + long groupId = groupEntity.getGroupId(); + GroupKey groupKey = new GroupKey(new GroupId(groupId)); + InstanceIdentifier groupInstanceId = InstanceIdentifier.builder(Nodes.class) + .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class) + .child(Group.class, groupKey).build(); + Runnable notifyTask = new NotifyTask(); + GroupInfoKey groupInfoKey = new GroupInfoKey(dpId, groupId); + synchronized (groupInfoKey.toString().intern()) { + s_logger.trace("syncsetupGroupKey groupKey {}", groupInfoKey); + groupMap.put(groupInfoKey, notifyTask); + if (isRemove) { + MDSALUtil.syncDelete(m_dataBroker, LogicalDatastoreType.CONFIGURATION, groupInstanceId); + } else { + MDSALUtil.syncWrite(m_dataBroker, LogicalDatastoreType.CONFIGURATION, groupInstanceId, group); + } + synchronized (notifyTask) { + try { + notifyTask.wait(delayTime); + } catch (InterruptedException e){} + } + } + } + } diff --git a/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALUtilProvider.java b/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALUtilProvider.java index b75bd4c4..c617cfcd 100644 --- a/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALUtilProvider.java +++ b/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALUtilProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, @@ -25,11 +25,14 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.ta import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.opendaylight.vpnservice.mdsalutil.FlowEntity; +import org.opendaylight.vpnservice.mdsalutil.GroupEntity; public class MDSALUtilProvider implements BindingAwareConsumer, IMdsalApiManager, AutoCloseable { private static final Logger s_logger = LoggerFactory.getLogger(MDSALUtilProvider.class); private MDSALManager mdSalMgr; + private static final long FIXED_DELAY_IN_MILLISECONDS = 5000; @Override public void onSessionInitialized(ConsumerContext session) { @@ -122,4 +125,19 @@ public class MDSALUtilProvider implements BindingAwareConsumer, IMdsalApiManager mdSalMgr.sendARPPacketOutWithActions(dpnId, payload, action_info); } + @Override + public void syncRemoveFlow(FlowEntity flowEntity, long delayTime) { + mdSalMgr.syncSetUpFlow(flowEntity, delayTime, true); + } + + @Override + public void syncInstallGroup(GroupEntity groupEntity, long delayTime) { + mdSalMgr.syncSetUpGroup(groupEntity, delayTime, false); + } + + @Override + public void syncRemoveGroup(GroupEntity groupEntity) { + mdSalMgr.syncSetUpGroup(groupEntity, FIXED_DELAY_IN_MILLISECONDS, true); + } + } diff --git a/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/NotifyTask.java b/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/NotifyTask.java new file mode 100644 index 00000000..d233baf5 --- /dev/null +++ b/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/NotifyTask.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.vpnservice.mdsalutil.internal; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +class NotifyTask implements Runnable { + private static final Logger logger = LoggerFactory.getLogger(NotifyTask.class); + + @Override + public void run() { + logger.debug("Notify Task is running for the task {}", this); + synchronized (this) { + notifyAll(); + } + } + +} diff --git a/nexthopmgr/nexthopmgr-impl/src/main/java/org/opendaylight/vpnservice/nexthopmgr/NexthopManager.java b/nexthopmgr/nexthopmgr-impl/src/main/java/org/opendaylight/vpnservice/nexthopmgr/NexthopManager.java old mode 100644 new mode 100755 index 4f384474..cb1447fb --- a/nexthopmgr/nexthopmgr-impl/src/main/java/org/opendaylight/vpnservice/nexthopmgr/NexthopManager.java +++ b/nexthopmgr/nexthopmgr-impl/src/main/java/org/opendaylight/vpnservice/nexthopmgr/NexthopManager.java @@ -34,7 +34,7 @@ import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev14081 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance; import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes; -import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstance1; +//import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstance1; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput; @@ -124,15 +124,18 @@ public class NexthopManager implements L3nexthopService, AutoCloseable { .child(VpnInstance.class, new VpnInstanceKey(vpnName)); InstanceIdentifier id = idBuilder.build(); - InstanceIdentifier idx = id.augmentation(VpnInstance1.class); - Optional vpn = read(LogicalDatastoreType.OPERATIONAL, idx); - - if (vpn.isPresent()) { - LOG.debug("VPN id returned: {}", vpn.get().getVpnId()); - return vpn.get().getVpnId(); - } else { - return -1; - } + //FIXME [ELAnBE] Commenting out below 2 lines + //InstanceIdentifier idx = id.augmentation(VpnInstance1.class); + //Optional vpn = read(LogicalDatastoreType.OPERATIONAL, idx); + + +// if (vpn.isPresent()) { +// LOG.debug("VPN id returned: {}", vpn.get().getVpnId()); +// return vpn.get().getVpnId(); +// } else { +// return -1; +// } + return -1; } private BigInteger getDpnId(String ofPortId) { diff --git a/pom.xml b/pom.xml index 0fdc1a45..eb4c800f 100644 --- a/pom.xml +++ b/pom.xml @@ -26,6 +26,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL vpnmanager interfacemgr alivenessmonitor + elanmanager fibmanager bgpmanager neutronvpn -- 2.36.6