--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>config-parent</artifactId>
+ <version>0.2.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>elanmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>yang-ext</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-inet-types</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-yang-types</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-interfaces</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>iana-if-type-2014-05-08</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-inventory</artifactId>
+ <version>${controller.mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>interfacemgr-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+/*
+ * 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<String> staticMacAddresses, String description);
+ public void updateElanInterface(String elanInstanceName, String interfaceName, List<String> 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<MacEntry> getElanMacTable(String elanInstanceName);
+ public void flushMACTable(String elanInstanceName);
+ public ElanInstance getElanInstance(String elanInstanceName);
+ public List<ElanInstance> getElanInstances();
+ public List<String> getElanInterfaces(String elanInstanceName);
+
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+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;
+ }
+ }
+ }
+}
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: --><!--
+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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>config-parent</artifactId>
+ <version>0.2.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>elanmanager-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>elanmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mdsalutil-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>interfacemgr-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>idmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>itm-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.console</artifactId>
+ <version>3.0.3</version>
+ </dependency>
+ </dependencies>
+
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+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
+-->
+<snapshot>
+ <required-capabilities>
+ <capability>urn:opendaylight:params:xml:ns:yang:elanservice:impl?module=elanservice-impl&revision=2015-02-16</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl?module=opendaylight-sal-binding-broker-impl&revision=2013-10-28</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:mdsalutil:api?module=odl-mdsalutil&revision=2015-04-10</capability>
+ <capability>urn:opendaylight:vpnservice:itm?module=itm&revision=2015-07-01</capability>
+ <capability>urn:opendaylight:vpnservice:interfacemgr?module=odl-interface&revision=2015-03-31</capability>
+ </required-capabilities>
+ <configuration>
+
+ <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:elanservice:impl">prefix:elanservice-impl</type>
+ <name>elanservice-default</name>
+ <broker>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+ <name>binding-osgi-broker</name>
+ </broker>
+ <rpcregistry>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+ <name>binding-rpc-broker</name>
+ </rpcregistry>
+ <mdsalutil>
+ <type xmlns:mdsalutil="urn:opendaylight:params:xml:ns:yang:mdsalutil:api">mdsalutil:odl-mdsalutil</type>
+ <name>mdsalutil-service</name>
+ </mdsalutil>
+ <odlinterface>
+ <type xmlns:odlif="urn:opendaylight:vpnservice:interfacemgr">odlif:odl-interface</type>
+ <name>interfacemgr-service</name>
+ </odlinterface>
+ <itmmanager>
+ <type xmlns:itm="urn:opendaylight:vpnservice:itm">itm:itm</type>
+ <name>itm</name>
+ </itmmanager>
+ <notification-service>
+ <type xmlns:bindingimpl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">bindingimpl:binding-new-notification-service</type>
+ <name>binding-notification-adapter</name>
+ </notification-service>
+ </module>
+ </modules>
+ <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <service>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:elanmanager:api">prefix:elanmanager-api</type>
+ <instance>
+ <name>elanmanager</name>
+ <provider>/modules/module[type='elanservice-impl'][name='elanservice-default']</provider>
+ </instance>
+ </service>
+ </services>
+ </data>
+ </configuration>
+</snapshot>
\ No newline at end of file
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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<ElanInstance> 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();
+ }
+}
+
--- /dev/null
+/*
+ * 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<String> 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;
+ }
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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<String> 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<ElanInstance> elanInstances = elanProvider.getElanInstances();
+ if(!elanInstances.isEmpty()) {
+ System.out.println(getElanInterfaceHeaderOutput());
+ for(ElanInstance elanInstance : elanInstances) {
+ List<String> 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<String> 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()));
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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<String> 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;
+ }
+}
+
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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<MacEntry> 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();
+ }
+}
+
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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<ElanInterface> implements AutoCloseable {
+ private DataBroker broker;
+ private ListenerRegistration<DataChangeListener> 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<MacEntry> 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<MacEntry> 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<MacEntry> 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<MacEntry> macEntryId = ElanUtils.getMacEntryOperationalDataPath(elanName, macEntry.getMacAddress());
+ Optional<MacEntry> 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<MacEntry> 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<MacEntry> macEntryId = ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress);
+ ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, macEntryId);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<ElanInterface> identifier, ElanInterface del) {
+
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<ElanInterface> identifier, ElanInterface original, ElanInterface update) {
+
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<ElanInterface> 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;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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<ElanInstance> implements AutoCloseable {
+ private DataBroker broker;
+ private static ElanInstanceManager elanInstanceManager = new ElanInstanceManager();
+ private ListenerRegistration<DataChangeListener> 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<ElanInstance> 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<String> elanInterfaces = existingElan.getElanInterfaces();
+ if(elanInterfaces != null && !elanInterfaces.isEmpty()) {
+ for (String elanInterfaceName : elanInterfaces) {
+ InstanceIdentifier<ElanInterface> 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<ElanInstance> 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<ElanInstance> identifier, ElanInstance elanInstanceAdded) {
+ Elan elanInfo = ElanUtils.getElanByName(elanInstanceAdded.getElanInstanceName());
+ if(elanInfo == null) {
+ ElanUtils.UpdateOperationalDataStore(broker, idManager, elanInstanceAdded);
+ }
+ }
+
+ public ElanInstance getElanInstanceByName(String elanInstanceName) {
+ InstanceIdentifier<ElanInstance> elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName);
+ Optional<ElanInstance> elanInstance = ElanUtils.read(broker, LogicalDatastoreType.CONFIGURATION, elanIdentifierId);
+ if(elanInstance.isPresent()) {
+ return elanInstance.get();
+ }
+ return null;
+ }
+
+ public List<DpnInterfaces> getElanDPNByName(String elanInstanceName) {
+ InstanceIdentifier<ElanDpnInterfacesList> elanIdentifier = getElanDpnOperationDataPath(elanInstanceName);
+ Optional<ElanDpnInterfacesList> elanInstance = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanIdentifier);
+ if(elanInstance.isPresent()) {
+ ElanDpnInterfacesList elanDPNs = elanInstance.get();
+ return elanDPNs.getDpnInterfaces();
+ }
+ return null;
+ }
+
+ private InstanceIdentifier<ElanDpnInterfacesList> getElanDpnOperationDataPath(String elanInstanceName) {
+ return InstanceIdentifier.builder(ElanDpnInterfaces.class).child(ElanDpnInterfacesList.class, new ElanDpnInterfacesListKey(elanInstanceName)).build();
+ }
+
+ private InstanceIdentifier<ElanInstance> getElanInstanceConfigurationDataPath(String elanInstanceName) {
+ return InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
+ }
+}
--- /dev/null
+/*
+ * 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<ElanInterface> implements AutoCloseable {
+
+ private static ElanInterfaceManager elanInterfaceManager = new ElanInterfaceManager();
+ private ListenerRegistration<DataChangeListener> elanInterfaceListenerRegistration;
+ private ListenerRegistration<DataChangeListener> itmInterfaceListenerRegistration;
+ private OdlInterfaceRpcService interfaceManagerRpcService;
+ private DataBroker broker;
+ private IMdsalApiManager mdsalManager;
+ private IInterfaceManager interfaceManager;
+ private IdManagerService idManager;
+ private IITMProvider itmManager;
+ private ElanForwardingEntriesHandler elanForwardingEntriesHandler;
+ private Map<String, ConcurrentLinkedQueue<ElanInterface>> unProcessedElanInterfaces =
+ new ConcurrentHashMap<String, ConcurrentLinkedQueue<ElanInterface>> ();
+
+ 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<ElanInterface> 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<MacEntry> 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<String> 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<ElanInterfaceMac> elanInterfaceId = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
+ Optional<ElanInterfaceMac> existingElanInterface = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
+ if(existingElanInterface.isPresent()) {
+ List<MacEntry> 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<DpnInterfaces> 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<String> 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<String> interfaceLists = dpnInterfaces.getInterfaces();
+ interfaceLists.remove(interfaceName);
+ updateElanDpnInterfacesList(elanName, dpId, interfaceLists);
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<ElanInterface> 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<PhysAddress> existingPhysAddress = original.getStaticMacEntries();
+ List<PhysAddress> updatedPhysAddress = update.getStaticMacEntries();
+ if(updatedPhysAddress != null && !updatedPhysAddress.isEmpty()) {
+ List<PhysAddress> 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<MacEntry> macId = getMacEntryOperationalDataPath(elanName, physAddress);
+ Optional<MacEntry> 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<ElanInterface> 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<ElanInterface> elanInterfaces = unProcessedElanInterfaces.get(elanInstanceName);
+ if (elanInterfaces == null) {
+ elanInterfaces = new ConcurrentLinkedQueue<ElanInterface>();
+ }
+ elanInterfaces.add(elanInterfaceAdded);
+ unProcessedElanInterfaces.put(elanInstanceName, elanInterfaces);
+ return;
+ }
+ addElanInterface(elanInterfaceAdded, interfaceInfo, elanInstance);
+ }
+
+ void handleunprocessedElanInterfaces(ElanInstance elanInstance) {
+ Queue<ElanInterface> 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<PhysAddress> 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<DpnInterfaces> elanDpnInterfaces = ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId);
+ Optional<DpnInterfaces> existingElanDpnInterfaces = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfaces);
+ if (!existingElanDpnInterfaces.isPresent()) {
+ createElanInterfacesList(elanInstanceName, interfaceName, dpId);
+ } else {
+ List<String> 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<MacEntry> macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress);
+ Optional<MacEntry> 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<BigInteger, List<String>> readFePortsDbForElan(String elanName) {
+ ElanDpnInterfacesList elanDpnInterfacesList = ElanUtils.getElanDpnInterfacesList(elanName);
+ HashMap<BigInteger, List<String>> fePortsDb = Maps.newHashMap();
+ if (elanDpnInterfacesList == null) {
+ return fePortsDb;
+ }
+ List<DpnInterfaces> 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<MacEntry> macId = getMacEntryOperationalDataPath(elanInstanceName, physAddress);
+ Optional<MacEntry> 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<MacEntry> 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<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ 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<ActionInfo> getEgressActionsForInterface(String ifName) {
+ List<ActionInfo> listActionInfo = new ArrayList<ActionInfo>();
+ try {
+ Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
+ interfaceManagerRpcService.getEgressActionsForInterface(
+ new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName).build());
+ RpcResult<GetEgressActionsForInterfaceOutput> 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<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> 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<BucketInfo> getRemoteBCGroupBucketInfos(ElanInstance elanInfo,
+ InterfaceInfo interfaceInfo) {
+ BigInteger dpnId = interfaceInfo.getDpId();
+ int elanTag = elanInfo.getElanTag().intValue();
+ List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
+ ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
+ if(elanDpns != null) {
+ List<DpnInterfaces> 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<ActionInfo> 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<ActionInfo> listActionInfo = new ArrayList<ActionInfo>();
+ 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<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
+ for(DpnInterfaces dpnInterface : dpnInterfaceses) {
+ List<BucketInfo> remoteListBucketInfo = new ArrayList<BucketInfo>();
+ 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<ActionInfo> 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<ActionInfo> remoteListActionInfo = new ArrayList<ActionInfo>();
+ 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<DpnInterfaces> elanDpns = ElanUtils.getInvolvedDpnsInElan(elanInfo.getElanInstanceName());
+ if(elanDpns != null) {
+ for(DpnInterfaces dpnInterface : elanDpns) {
+ List<BucketInfo> remoteListBucketInfo = new ArrayList<BucketInfo>();
+ 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<ActionInfo> 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<ActionInfo> remoteListActionInfo = new ArrayList<ActionInfo>();
+ 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<BucketInfo> getLocalBCGroupBucketInfo(InterfaceInfo interfaceInfo) {
+ return Lists.newArrayList(new BucketInfo(getInterfacePortActionInfos(interfaceInfo)));
+ }
+
+ private List<MatchInfo> getMatchesForElanTag(Long elanTag) {
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ // Matching metadata
+ mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ ElanUtils.getElanMetadataLabel(elanTag),
+ MetaDataUtil.METADATA_MASK_SERVICE }));
+ return mkMatches;
+ }
+
+ private List<InstructionInfo> getInstructionsForOutGroup(
+ long groupId) {
+ List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
+ List <ActionInfo> actionsInfos = new ArrayList <ActionInfo> ();
+ 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<MacEntry> 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<DpnInterfaces> dpnInterfaceLists = elanDpnInterfacesList.getDpnInterfaces();
+ for(DpnInterfaces dpnInterfaces : dpnInterfaceLists){
+ if(dpnInterfaces.getDpId().equals(interfaceInfo.getDpId())) {
+ continue;
+ }
+ List<String> remoteElanInterfaces = dpnInterfaces.getInterfaces();
+ for(String remoteIf : remoteElanInterfaces) {
+ ElanInterfaceMac elanIfMac = ElanUtils.getElanInterfaceMacByInterfaceName(remoteIf);
+ InterfaceInfo remoteInterface = interfaceManager.getInterfaceInfo(remoteIf);
+ if(elanIfMac == null) {
+ continue;
+ }
+ List<MacEntry> 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<MacEntry> 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<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
+ for(MacEntry macEntry : macEntries) {
+ ElanUtils.deleteMacFlows(elanInfo, interfaceInfo, macEntry);
+ }
+ }
+ }
+
+ public void setupLocalBroadcastGroups(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
+ List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
+ 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<BucketInfo> 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<BucketInfo> 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 <String> 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<Instruction> instructions = new ArrayList<Instruction>();
+ 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<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ // Matching metadata
+ mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ ElanUtils.getElanMetadataLabel(elanTag),
+ MetaDataUtil.METADATA_MASK_SERVICE }));
+
+ List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
+ List <ActionInfo> actionsInfos = new ArrayList <ActionInfo> ();
+ 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<ActionInfo> getInterfacePortActionInfos(InterfaceInfo interfaceInfo) {
+ List<ActionInfo> listActionInfo = new ArrayList<ActionInfo>();
+ listActionInfo.add(getReg1ActionInfo(interfaceInfo.getInterfaceTag()));
+ listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[]{}));
+ return listActionInfo;
+ }
+
+ private void updateElanDpnInterfacesList(String elanInstanceName, BigInteger dpId, List<String> 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<String> createElanInterfacesList(String elanInstanceName, String interfaceName, BigInteger dpId) {
+ List<String> interfaceNames = new ArrayList<String>();
+ 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<ElanInterfaceMac> elanInterfaceMacTables = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
+ Optional<ElanInterfaceMac> 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<Elan> elanInstance = ElanUtils.getElanInstanceOperationalDataPath(elanInstanceName);
+ Optional<Elan> elanInterfaceLists = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInstance);
+ // Adding new Elan Interface Port to the operational DataStore without Static-Mac Entries..
+ if(elanInterfaceLists.isPresent()) {
+ List<String> 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<ElanInterfaceMac> elanInterfaceId = ElanUtils.getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
+ Optional<ElanInterfaceMac> existingElanInterface = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
+ ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanInterface.getElanInstanceName());
+
+ if(!existingElanInterface.isPresent()) {
+ return;
+ }
+
+ List<MacEntry> 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<DpnInterfaces> dpnInterfaceId = ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInterface.getElanInstanceName(), interfaceInfo.getDpId());
+ Optional<DpnInterfaces> dpnInterfaces = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, dpnInterfaceId);
+ List<String> 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<String> elanInstancesMap = new HashSet<>();
+ if(dpnInterfaceLists == null) {
+ return;
+ }
+ List<ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists.getElanDpnInterfacesList();
+ for(ElanDpnInterfacesList elanDpns: elanDpnIf) {
+ int cnt = 0;
+ String elanName = elanDpns.getElanInstanceName();
+ List<DpnInterfaces> 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<String> 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<String> 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<String> 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<MatchInfo> getMatchesForFilterEqualsLPortTag(Long LportTag) {
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ // 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<MatchInfo> getMatchesForFilterEqualsReg1LPortTag(Long LportTag) {
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ // Matching metadata
+ mkMatches.add(new MatchInfo(MatchFieldType.reg1, new long[] {
+ (LportTag.longValue())}));
+ return mkMatches;
+
+
+ }
+
+ public static class RegMatch {
+
+ final Class<? extends NxmNxReg> reg;
+ final Long value;
+
+ public RegMatch(Class<? extends NxmNxReg> reg, Long value) {
+ super();
+ this.reg = reg;
+ this.value = value;
+ }
+
+ public static RegMatch of(Class<? extends NxmNxReg> reg, Long value) {
+ return new RegMatch(reg, value);
+ }
+ }
+
+ public static void addNxRegMatch(MatchBuilder match, RegMatch... matches) {
+ ArrayList<ExtensionList> extensions = new ArrayList<>();
+ for (RegMatch rm : matches) {
+ Class<? extends ExtensionKey> 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<InstructionInfo> getInstructionsInPortForOutGroup(
+ long GroupId) {
+ List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
+ List <ActionInfo> actionsInfos = new ArrayList <ActionInfo> ();
+ 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<InstructionInfo> getInstructionsInPortForOutGroup(
+ String ifName) {
+ List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
+ List <ActionInfo> actionsInfos = new ArrayList <ActionInfo> ();
+ //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<InstructionInfo> getInstructionsDrop() {
+ List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
+ List <ActionInfo> actionsInfos = new ArrayList <ActionInfo> ();
+ actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[]{}));
+ mkInstructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos));
+ return mkInstructions;
+ }
+
+}
--- /dev/null
+/*
+ * 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<DataObject> 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<DataChangeListener> 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<StateTunnelList> 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<StateTunnelList> identifier, StateTunnelList del) {
+//
+// }
+//
+// @Override
+// protected void update(InstanceIdentifier<StateTunnelList> 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<StateTunnelList> 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);
+// }
+// }
+//}
--- /dev/null
+/*
+ * 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<Node> {
+
+ private static final Logger logger = LoggerFactory.getLogger(ElanNodeListener.class);
+
+ private IMdsalApiManager mdsalManager;
+ private ListenerRegistration<DataChangeListener> 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<Node> getWildCardPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class);
+ }
+
+
+ @Override
+ protected void remove(InstanceIdentifier<Node> identifier, Node del) {
+
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Node> identifier, Node original, Node update) {
+
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Node> 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<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
+ List <ActionInfo> actionsInfos = new ArrayList <ActionInfo> ();
+ 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<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+
+ List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
+ 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();
+ }
+}
--- /dev/null
+/*
+ * 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<? extends PacketInReason> 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<MacEntry> 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<MacEntry> 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<MacEntry> macEntryId = ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, macEntryId, macEntry);
+ InstanceIdentifier<MacEntry> 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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<RpcResult<Void>> 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<String> 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<String> updatedStaticMacAddresses, String newDescription) {
+ ElanInterface existingElanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName);
+ if (existingElanInterface == null) {
+ return;
+ }
+ List<PhysAddress> existingMacAddress = existingElanInterface.getStaticMacEntries();
+ List<PhysAddress> updatedMacAddresses = getPhysAddress(updatedStaticMacAddresses);
+ List<PhysAddress> 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<PhysAddress> 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<PhysAddress> 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<MacEntry> getElanMacTable(String elanInstanceName) {
+ Elan elanInfo = ElanUtils.getElanByName(elanInstanceName);
+ List<MacEntry> macAddress = new ArrayList<>();
+ if(elanInfo == null) {
+ return macAddress;
+ }
+ List<String> 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<String> 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<MacEntry> 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<PhysAddress> getPhysAddress(List<String> macAddress) {
+ List<PhysAddress> physAddresses = new ArrayList<>();
+ for(String mac : macAddress) {
+ physAddresses.add(new PhysAddress(mac));
+ }
+ return physAddresses;
+ }
+
+
+ public List<PhysAddress> getUpdatedPhyAddress(List<PhysAddress> originalAddresses, List<PhysAddress> updatePhyAddresses) {
+ if(updatePhyAddresses != null && !updatePhyAddresses.isEmpty()) {
+ List<PhysAddress> 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<ElanInstance> getElanInstances() {
+ List<ElanInstance> elanList = new ArrayList<ElanInstance>();
+ InstanceIdentifier<ElanInstances> elanInstancesIdentifier = InstanceIdentifier.builder(ElanInstances.class).build();
+ Optional<ElanInstances> elansOptional = ElanUtils.read(broker, LogicalDatastoreType.CONFIGURATION, elanInstancesIdentifier);
+ if(elansOptional.isPresent()) {
+ elanList.addAll(elansOptional.get().getElanInstance());
+ }
+ return elanList;
+ }
+
+ @Override
+ public List<String> getElanInterfaces(String elanInstanceName) {
+ List<String> elanInterfaces = new ArrayList<>();
+ InstanceIdentifier<ElanInterfaces> elanInterfacesIdentifier = InstanceIdentifier.builder(ElanInterfaces.class).build();
+ Optional<ElanInterfaces> elanInterfacesOptional = ElanUtils.read(broker, LogicalDatastoreType.CONFIGURATION, elanInterfacesIdentifier);
+ if(!elanInterfacesOptional.isPresent()) {
+ return elanInterfaces;
+ }
+ List<ElanInterface> elanInterfaceList = elanInterfacesOptional.get().getElanInterface();
+ for(ElanInterface elanInterface : elanInterfaceList) {
+ if(elanInterface.getElanInstanceName().equals(elanInstanceName)) {
+ elanInterfaces.add(elanInterface.getName());
+ }
+ }
+ return elanInterfaces;
+ }
+}
--- /dev/null
+/*
+ * 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<MacEntry> macEntryId = ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress);
+ ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, macEntryId);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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<RpcResult<GetElanInterfaceStatisticsOutput>> getElanInterfaceStatistics(
+ GetElanInterfaceStatisticsInput input) {
+ String interfaceName = input.getInterfaceName();
+ logger.debug("getElanInterfaceStatistics is called for elan interface {}", interfaceName);
+ RpcResultBuilder<GetElanInterfaceStatisticsOutput> 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<MatchInfo> 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<Object> 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<RpcResult<GetElanInterfaceStatisticsOutput>> getFutureWithAppErrorMessage(
+ RpcResultBuilder<GetElanInterfaceStatisticsOutput> rpcResultBuilder, String message) {
+ rpcResultBuilder.withError(ErrorType.APPLICATION, message);
+ return Futures.immediateFuture(rpcResultBuilder.build());
+ }
+
+}
--- /dev/null
+/*
+ * 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 ";
+}
--- /dev/null
+/*
+ * 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);
+
+
+}
--- /dev/null
+/*
+ * 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<Void> DEFAULT_CALLBACK =
+ new FutureCallback<Void>() {
+ 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<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
+ RpcResult<AllocateIdOutput> 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<RpcResult<Void>> result = idManager.releaseId(releaseIdInput);
+ }
+
+ public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path) {
+
+ ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
+
+ Optional<T> result = Optional.absent();
+ try {
+ result = tx.read(datastoreType, path).get();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ return result;
+ }
+
+
+ public static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.delete(datastoreType, path);
+ Futures.addCallback(tx.submit(), DEFAULT_CALLBACK);
+ }
+
+ public static InstanceIdentifier<ElanInstance> getElanInstanceIdentifier(String elanName) {
+ return InstanceIdentifier.builder(ElanInstances.class)
+ .child(ElanInstance.class, new ElanInstanceKey(elanName)).build();
+ }
+
+ public static InstanceIdentifier<ElanInstance> 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<ElanInstance> elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName);
+ Optional<ElanInstance> elanInstance = read(broker, LogicalDatastoreType.CONFIGURATION, elanIdentifierId);
+ if(elanInstance.isPresent()) {
+ return elanInstance.get();
+ }
+ return null;
+ }
+
+ public static InstanceIdentifier<ElanInstance> 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<ElanInterface> elanInterfaceId = getElanInterfaceConfigurationDataPathId(elanInterfaceName);
+ Optional<ElanInterface> existingElanInterface = read(broker, LogicalDatastoreType.CONFIGURATION, elanInterfaceId);
+ if(existingElanInterface.isPresent()) {
+ return existingElanInterface.get();
+ }
+ return null;
+ }
+
+ public static class RegMatch {
+
+ final Class<? extends NxmNxReg> reg;
+ final Long value;
+
+ public RegMatch(Class<? extends NxmNxReg> reg, Long value) {
+ super();
+ this.reg = reg;
+ this.value = value;
+ }
+
+ public static RegMatch of(Class<? extends NxmNxReg> reg, Long value) {
+ return new RegMatch(reg, value);
+ }
+ }
+
+ public static void addNxRegMatch(MatchBuilder match, RegMatch... matches) {
+ ArrayList<ExtensionList> extensions = new ArrayList<>();
+ for (RegMatch rm : matches) {
+ Class<? extends ExtensionKey> 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<ElanInterface> 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<Elan> elanIdentifier = getElanInstanceOperationalDataPath(elanInstanceName);
+ Optional<Elan> elanInstance = read(broker, LogicalDatastoreType.OPERATIONAL, elanIdentifier);
+ if(elanInstance.isPresent()) {
+ return elanInstance.get();
+ }
+ return null;
+ }
+
+ public static InstanceIdentifier<Elan> 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<MacEntry> existingMacEntryId = getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress);
+ Optional<MacEntry> 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<MacEntry> existingInterfaceMacEntry = read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
+ if(existingInterfaceMacEntry.isPresent()) {
+ return existingInterfaceMacEntry.get();
+ }
+ return null;
+ }
+
+ public static InstanceIdentifier<MacEntry> 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<MacEntry> macId = getMacEntryOperationalDataPath(elanName, physAddress);
+ Optional<MacEntry> 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<MacEntry> existingInterfaceMacEntry = read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
+ if(existingInterfaceMacEntry.isPresent()) {
+ return existingInterfaceMacEntry.get();
+ }
+ return null;
+ }
+
+ public static InstanceIdentifier<MacEntry> 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<MacTable> 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<ElanInterfaceMac> elanInterfaceId = getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
+ Optional<ElanInterfaceMac> existingElanInterface = read(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
+ if(existingElanInterface.isPresent()) {
+ return existingElanInterface.get();
+ }
+ return null;
+ }
+
+ public static InstanceIdentifier<ElanInterfaceMac> 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<DpnInterfaces> elanDpnInterfacesId = getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId);
+ Optional<DpnInterfaces> elanDpnInterfaces = read(broker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfacesId);
+ if(elanDpnInterfaces.isPresent()) {
+ return elanDpnInterfaces.get();
+ }
+ return null;
+ }
+
+ public static InstanceIdentifier<DpnInterfaces> 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<ElanTagName> elanId = getElanInfoEntriesOperationalDataPath(elanTag);
+ Optional<ElanTagName> existingElanInfo = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanId);
+ if(existingElanInfo.isPresent()) {
+ return existingElanInfo.get();
+ }
+ return null;
+ }
+
+ public static InstanceIdentifier<ElanTagName> 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<IfIndexInterface> interfaceId = getInterfaceInfoEntriesOperationalDataPath(interfaceTag);
+ Optional<IfIndexInterface> existingInterfaceInfo = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
+ if(existingInterfaceInfo.isPresent()) {
+ return existingInterfaceInfo.get();
+ }
+ return null;
+ }
+
+ public static InstanceIdentifier<IfIndexInterface> getInterfaceInfoEntriesOperationalDataPath(long interfaceTag) {
+ return InstanceIdentifier.builder(IfIndexesInterfaceMap.class).child(IfIndexInterface.class,
+ new IfIndexInterfaceKey((int) interfaceTag)).build();
+ }
+
+
+
+ public static InstanceIdentifier<ElanDpnInterfacesList> 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<ElanDpnInterfacesList> elanDpnInterfaceId = getElanDpnOperationDataPath(elanName);
+ Optional<ElanDpnInterfacesList> existingElanDpnInterfaces = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
+ if(existingElanDpnInterfaces.isPresent()) {
+ return existingElanDpnInterfaces.get();
+ }
+ return null;
+ }
+
+ public static ElanDpnInterfaces getElanDpnInterfacesList() {
+ DataBroker broker = elanServiceProvider.getBroker();
+ InstanceIdentifier<ElanDpnInterfaces> elanDpnInterfaceId = InstanceIdentifier.builder(ElanDpnInterfaces.class).build();
+ Optional<ElanDpnInterfaces> existingElanDpnInterfaces = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
+ if(existingElanDpnInterfaces.isPresent()) {
+ return existingElanDpnInterfaces.get();
+ }
+ return null;
+ }
+
+ public static ElanForwardingTables getElanForwardingList() {
+ DataBroker broker = elanServiceProvider.getBroker();
+ InstanceIdentifier<ElanForwardingTables> elanForwardingTableId = InstanceIdentifier.builder(ElanForwardingTables.class).build();
+ Optional<ElanForwardingTables> 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<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ 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<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
+ 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 <ActionInfo> actionsInfos = new ArrayList <ActionInfo> ();
+ 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<ActionInfo> getEgressActionsForInterface(String ifName) {
+ List<ActionInfo> listActionInfo = new ArrayList<ActionInfo>();
+ try {
+ Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
+ elanServiceProvider.getInterfaceManagerRpcService().getEgressActionsForInterface(
+ new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName).build());
+ RpcResult<GetEgressActionsForInterfaceOutput> 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<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action> 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<DpnInterfaces> 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<DpnInterfaces> 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<DpnInterfaces> getInvolvedDpnsInElan(String elanName) {
+ List<DpnInterfaces> 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<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ 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<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
+ List <ActionInfo> actionsInfos = new ArrayList <ActionInfo> ();
+ 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<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ 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<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
+ //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<ActionInfo> 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<DpnInterfaces> 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> node = InstanceIdentifier.builder(Nodes.class).child(Node.class, new NodeKey(nodeId)).build();
+ Optional<Node> 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<Instruction> instructions = new ArrayList<Instruction>();
+ 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 <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.delete(datastoreType, path);
+ Futures.addCallback(tx.submit(), callback);
+ }
+
+ public static <T extends DataObject> void syncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.put(datastoreType, path, data, true);
+ CheckedFuture<Void, TransactionCommitFailedException> 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<Instruction> 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<BoundServices> buildServiceId(String vpnInterfaceName, short serviceIndex) {
+ return InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class, new ServicesInfoKey(vpnInterfaceName))
+ .child(BoundServices.class, new BoundServicesKey(serviceIndex)).build();
+ }
+
+}
--- /dev/null
+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;
+ }
+
+}
--- /dev/null
+/*
+* 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 {
+
+}
--- /dev/null
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+ <reference id="elanProviderRef" interface="org.opendaylight.elanmanager.api.IElanService" availability="optional" />
+ <reference id="interfaceManagerRef" interface="org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager" availability="optional" />
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+ <command>
+ <action class="org.opendaylight.vpnservice.elan.cli.ElanAdd">
+ <property name="elanProvider" ref="elanProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.elan.cli.ElanDelete">
+ <property name="elanProvider" ref="elanProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.elan.cli.ElanUpdate">
+ <property name="elanProvider" ref="elanProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.elan.cli.ElanInterfaceAdd">
+ <property name="elanProvider" ref="elanProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.elan.cli.ElanInterfaceDelete">
+ <property name="elanProvider" ref="elanProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.elan.cli.ElanInterfaceUpdate">
+ <property name="elanProvider" ref="elanProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.elan.cli.StaticMacAdd">
+ <property name="elanProvider" ref="elanProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.elan.cli.StaticMacDelete">
+ <property name="elanProvider" ref="elanProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.elan.cli.ElanMacTableGet">
+ <property name="elanProvider" ref="elanProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.elan.cli.ElanMacTableFlush">
+ <property name="elanProvider" ref="elanProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.elan.cli.ElanGet">
+ <property name="elanProvider" ref="elanProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.elan.cli.ElanInterfaceGet">
+ <property name="elanProvider" ref="elanProviderRef" />
+ <property name="interfaceManager" ref="interfaceManagerRef" />
+ </action>
+ </command>
+ </command-bundle>
+</blueprint>
\ No newline at end of file
--- /dev/null
+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
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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 INTERNAL
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <parent>
+ <groupId>org.opendaylight.odlparent</groupId>
+ <artifactId>odlparent</artifactId>
+ <version>1.6.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>elanmanager</artifactId>
+ <version>0.2.0-SNAPSHOT</version>
+ <name>elanmanager</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>elanmanager-api</module>
+ <module>elanmanager-impl</module>
+ </modules>
+ <!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build -->
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
<mdsalutil.version>${vpnservices.version}</mdsalutil.version>
<vpnmanager.version>${vpnservices.version}</vpnmanager.version>
<interfacemgr.version>${vpnservices.version}</interfacemgr.version>
+ <elanmgr.version>${vpnservices.version}</elanmgr.version>
<nexthopmgr.version>${vpnservices.version}</nexthopmgr.version>
<fibmanager.version>${vpnservices.version}</fibmanager.version>
<lockmanager.version>${vpnservices.version}</lockmanager.version>
<artifactId>interfacemgr-api</artifactId>
<version>${interfacemgr.version}</version>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>elanmanager-impl</artifactId>
+ <version>${elanmgr.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>elanmanager-impl</artifactId>
+ <version>${elanmgr.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>elanmanager-api</artifactId>
+ <version>${elanmgr.version}</version>
+ </dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>liblldp</artifactId>
<artifactId>libthrift</artifactId>
<version>0.9.1</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>features-openflowplugin-extension</artifactId>
+ <classifier>features</classifier>
+ <version>${openflowplugin.version}</version>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<repository>mvn:org.opendaylight.controller/features-mdsal/${mdsal.version}/xml/features</repository>
<repository>mvn:org.opendaylight.mdsal.model/features-mdsal-model/${mdsal.model.version}/xml/features</repository>
<repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin/${openflowplugin.version}/xml/features</repository>
+ <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin-extension/${openflowplugin.version}/xml/features</repository>
<repository>mvn:org.opendaylight.netconf/features-restconf/${restconf.version}/xml/features</repository>
<repository>mvn:org.opendaylight.ovsdb/features-ovsdb/${ovsdb.version}/xml/features</repository>
<repository>mvn:org.opendaylight.neutron/features-neutron/${neutron.version}/xml/features</repository>
<feature version='${mdsal.version}'>odl-mdsal-broker</feature>
<feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
<feature version='${openflowplugin.version}'>odl-openflowplugin-nsf-model</feature>
+ <feature version="${openflowplugin.version}">odl-openflowplugin-nxm-extensions</feature>
<feature version="${ovsdb.version}">odl-ovsdb-southbound-impl-rest</feature>
<bundle>mvn:org.opendaylight.controller/liblldp/${liblldp.version}</bundle>
<bundle>mvn:org.opendaylight.neutron/model/${neutron.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/neutronvpn-impl/${neutronvpn.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/neutronvpn-shell/${neutronvpn.version}</bundle>
<bundle>mvn:org.opendaylight.vpnservice/dhcpservice-impl/${vpnservices.version}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/elanmanager-api/${elanmgr.version}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/elanmanager-impl/${elanmgr.version}</bundle>
<!--<bundle>mvn:org.opendaylight.vpnservice.third-party/org.apache.thriftlib/1.0.1-SNAPSHOT</bundle>-->
<bundle>wrap:mvn:org.apache.thrift/libthrift/0.9.1$overwrite=merge&Bundle-Version=0.9.1&Export-Package=*;-noimport:=true;version="0.9.1"</bundle>
<configfile finalname="itm-impl-default-config.xml">mvn:org.opendaylight.vpnservice/itm-impl/${itm.version}/xml/config</configfile>
<configfile finalname="neutronvpn-impl-default-config.xml">mvn:org.opendaylight.vpnservice/neutronvpn-impl/${neutronvpn.version}/xml/config</configfile>
<configfile finalname="dhcpservice-impl-default-config.xml">mvn:org.opendaylight.vpnservice/dhcpservice-impl/${vpnservices.version}/xml/config</configfile>
+ <configfile finalname="elanmanager-impl-default-config.xml">mvn:org.opendaylight.vpnservice/elanmanager-impl/${elanmgr.version}/xml/config</configfile>
+
</feature>
<feature name='odl-vpnservice-impl-rest' version='${project.version}' description='OpenDaylight :: vpnservice :: impl :: REST '>
<feature version="${project.version}">odl-vpnservice-impl</feature>
--- /dev/null
+/*
+ * 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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<Instruction> instructions) {
+ List<BoundServices> boundService = new ArrayList<BoundServices>();
+ 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<BoundServices> boundService = new ArrayList<BoundServices>();
+ boundService.add(new BoundServicesBuilder().setServicePriority((short)servicePriority).setServiceName(serviceName).build());
+ return new ServicesInfoBuilder().setBoundServices(boundService).setKey(new ServicesInfoKey(serviceName)).build();
+ }
+
+ public static List<MatchInfo> getMatchInfoForVlanLPort(BigInteger dpId, long portNo, long vlanId, boolean isVlanTransparent) {
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ 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<Interface> id = InstanceIdentifier.builder(Interfaces.class)
+ .child(Interface.class, new InterfaceKey(interfaceName)).build();
+ Optional<Interface> 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<Object> getStatRequestKeys(BigInteger dpId, short tableId, List<MatchInfo> matches, String flowId, long groupId) {
+ Set<Object> statRequestKeys = new HashSet<Object>();
+ 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<MatchInfo> matches, String flowId) {
+ return new FlowInfoKey(dpId, tableId, MDSALUtil.buildMatches(matches), flowId);
+ }
+
+ public static List<MatchInfo> getLPortDispatcherMatches(short serviceIndex, int interfaceTag) {
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ MetaDataUtil.getMetaDataForLPortDispatcher(interfaceTag, serviceIndex),
+ MetaDataUtil.getMetaDataMaskForLPortDispatcher() }));
+ return mkMatches;
+ }
+
+}
--- /dev/null
+/*
+ * 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<String> parentInterfaceNames;
+
+ public LogicalGroupInterfaceInfo(String portName, BigInteger srcDpId,List<String> pInterfaces) {
+ super(srcDpId,portName);
+
+ parentInterfaceNames = new ArrayList(pInterfaces);
+ }
+
+ public List<String> 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);
+ }
+
+}
+
+/*--------------------------------*/
+
--- /dev/null
+/*
+ * 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;
+ }
+}
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 {
@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
--- /dev/null
+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;
+ }
+ }
+ }
+
+}
/*
- * 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,
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);
}
/*
- * 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,
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;
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;
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;
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<String> getDpIdPortNameAndSuffixFromInterfaceName(String intfName) {
List<String> strList = new ArrayList<>(3);
int index1 = intfName.indexOf(":");
}
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<? extends org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType> 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<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase> 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;
+ }
+
+
+
}
/*
- * 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,
*/
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);
private FlowBasedServicesInterfaceStateListener flowBasedServicesInterfaceStateListener;
private FlowBasedServicesConfigListener flowBasedServicesConfigListener;
private VlanMemberConfigListener vlanMemberConfigListener;
-
+ private DataBroker dataBroker;
private InterfaceManagerRpcService interfaceManagerRpcService;
private BindingAwareBroker.RpcRegistration<OdlInterfaceRpcService> rpcRegistration;
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();
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();
/*
- * 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,
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;
}
<artifactId>liblldp</artifactId>
<version>${liblldp.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>openflowplugin-extension-nicira</artifactId>
+ <version>${openflowplugin.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>openflowjava-extension-nicira</artifactId>
+ <version>${openflowplugin.version}</version>
+ </dependency>
+
</dependencies>
</project>
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;
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;
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
}
},
+
drop_action {
@Override
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
--- /dev/null
+/*
+ * 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 + "]";
+ }
+
+}
--- /dev/null
+/*
+ * 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 + "]";
+ }
+
+}
return EMPTY_Instructions;
}
- protected static Match buildMatches(List<MatchInfo> listMatchInfo) {
+ public static Match buildMatches(List<MatchInfo> listMatchInfo) {
if (listMatchInfo != null) {
MatchBuilder matchBuilder = new MatchBuilder();
Map<Class<?>, Object> mapMatchBuilder = new HashMap<Class<?>, Object>();
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;
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;
},
+ reg1 {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return MatchField.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, 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<ExtensionList> 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<Class<?>, Object> mapMatchBuilder) {
+ List<ExtensionList> 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<? extends MatchField> getMatchType() {
/*
- * 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,
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 {
public void sendARPPacketOutWithActions(BigInteger dpnId, byte[] payload, List<ActionInfo> 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);
}
/*
- * 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,
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;
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;
private DataBroker m_dataBroker;
private PacketProcessingService m_packetProcessingService;
+ private ConcurrentMap<FlowInfoKey, Runnable> flowMap = new ConcurrentHashMap<FlowInfoKey, Runnable>();
+ private ConcurrentMap<GroupInfoKey, Runnable> groupMap = new ConcurrentHashMap<GroupInfoKey, Runnable> ();
/**
* Writes the flows and Groups to the MD SAL DataStore
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<Flow> 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<Group> 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){}
+ }
+ }
+ }
+
}
/*
- * 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,
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) {
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);
+ }
+
}
--- /dev/null
+/*
+ * 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();
+ }
+ }
+
+}
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;
.child(VpnInstance.class, new VpnInstanceKey(vpnName));
InstanceIdentifier<VpnInstance> id = idBuilder.build();
- InstanceIdentifier<VpnInstance1> idx = id.augmentation(VpnInstance1.class);
- Optional<VpnInstance1> 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<VpnInstance1> idx = id.augmentation(VpnInstance1.class);
+ //Optional<VpnInstance1> 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) {
<module>vpnmanager</module>
<module>interfacemgr</module>
<module>alivenessmonitor</module>
+ <module>elanmanager</module>
<module>fibmanager</module>
<module>bgpmanager</module>
<module>neutronvpn</module>