--- /dev/null
+#
+# Copyright (c) 2015 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
+#
+.classpath
+.project
+.settings
+.metadata
+target
+*.iml
+.idea
+bin
+xtend-gen
+target
+.DS_Store
+.checkstyle
+yang-gen-config
+yang-gen-sal
+classes
+maven-metadata-local.xml
+META-INF
--- /dev/null
+[gerrit]
+host=git.opendaylight.org
+port=29418
+project=vpnservice.git
+defaultbranch=master
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>alivenessmonitor-api</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>liblldp</artifactId>
+ <version>${liblldp.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-inet-types</artifactId>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+module aliveness-monitor {
+ namespace "urn:opendaylight:vpnservice:alivenessmonitor";
+ prefix alivenessmon;
+
+ import ietf-inet-types {
+ prefix inet;
+ revision-date "2010-09-24";
+ }
+
+ revision "2015-06-29" {
+ description "YANG model describes methods for monitoring endpoints.";
+ }
+
+ typedef ether-types {
+ type enumeration {
+ enum arp;
+ enum lldp;
+ }
+ }
+
+ typedef monitoring-mode {
+ type enumeration {
+ enum one-one;
+ }
+ }
+
+ grouping endpoint {
+ choice endpoint-type {
+ case ip-address {
+ leaf ip-address { type inet:ip-address; }
+ }
+ case interface {
+ leaf interface-ip { type inet:ip-address; }
+ leaf interface-name { type string; }
+ }
+ case host-name {
+ leaf host-name { type string; }
+ }
+ }
+ }
+
+ grouping monitor-profile-params {
+ leaf monitor-interval { type uint32; } //Monitoring interval in milli-seconds
+ leaf monitor-window { type uint32; } //Number M of consecutive intervals to consider for monitoring
+ leaf failure-threshold { type uint32; } //Number N of missing messages in window to detect failure ("N out of M")
+ leaf protocol-type { type ether-types; }
+ }
+
+ grouping monitor-params {
+ leaf mode { type monitoring-mode; }
+ container source { uses endpoint; }
+ container destination { uses endpoint; }
+ leaf profile-id { type uint32; }
+ }
+
+ // RPC Methods
+ rpc monitor-profile-create {
+ input {
+ container profile {
+ uses monitor-profile-params;
+ }
+ }
+ output {
+ leaf profile-id { type uint32; }
+ }
+ }
+
+ rpc monitor-profile-get {
+ input {
+ container profile {
+ uses monitor-profile-params;
+ }
+ }
+ output {
+ leaf profile-id { type uint32; }
+ }
+ }
+
+ rpc monitor-start {
+ input {
+ container config {
+ uses monitor-params;
+ }
+ }
+ output {
+ leaf monitor-id { type uint32; }
+ }
+ }
+
+ rpc monitor-pause {
+ input {
+ leaf monitor-id { type uint32; }
+ }
+ }
+
+ rpc monitor-unpause {
+ input {
+ leaf monitor-id { type uint32; }
+ }
+ }
+
+
+ rpc monitor-stop {
+ input {
+ leaf monitor-id { type uint32; }
+ }
+ }
+
+ rpc monitor-profile-delete {
+ input {
+ leaf profile-id { type uint32; }
+ }
+ }
+
+ // YANG Notifications
+ typedef liveness-state {
+ type enumeration {
+ enum up;
+ enum down;
+ enum unknown;
+ }
+ }
+
+ grouping liveness-event-state {
+ leaf monitor-id { type uint32; }
+ leaf monitor-state { type liveness-state; }
+ }
+
+ notification monitor-event {
+ container event-data {
+ uses liveness-event-state;
+ }
+ }
+
+ //Operational Model
+ container monitor-profiles {
+ config false;
+ list monitor-profile {
+ key "id";
+ leaf id { type uint32; }
+ uses monitor-profile-params;
+ }
+ }
+
+ container monitor-configs {
+ config false;
+ list monitoring-info {
+ key "id";
+ leaf id { type uint32; }
+ uses monitor-params;
+ }
+ }
+
+ typedef monitor-status {
+ type enumeration {
+ enum started;
+ enum paused;
+ enum stopped;
+ }
+ }
+
+ container monitoring-states {
+ config false;
+ list monitoring-state {
+ key "monitor-key";
+ leaf monitor-key { type string; } //Key to identify monitor-id from packet-in
+ leaf monitor-id { type uint32; }
+ leaf response-pending-count { type uint32; }
+ leaf request-count { type uint32; }
+ leaf state { type liveness-state; }
+ leaf status { type monitor-status; }
+ }
+ }
+
+ container monitorid-key-map {
+ config false;
+ list monitorid-key-entry {
+ key "monitor-id";
+ leaf monitor-id { type uint32; }
+ leaf monitor-key { type string; }
+ }
+ }
+
+ container interface-monitor-map {
+ config false;
+ list interface-monitor-entry {
+ key "interface-name";
+ leaf interface-name { type string; }
+ leaf-list monitor-ids { type uint32; }
+ }
+ }
+}
\ 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) 2015 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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>alivenessmonitor-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>alivenessmonitor-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>liblldp</artifactId>
+ <version>${liblldp.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>mdsalutil-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.model</groupId>
+ <artifactId>model-flow-service</artifactId>
+ <version>${openflowplugin.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller.model</groupId>
+ <artifactId>model-inventory</artifactId>
+ <version>${controller.mdsal.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-interfaces</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>idmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>interfacemgr-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>arputil-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ </dependencies>
+
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright (c) 2015 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:alivenessmonitor:impl?module=alivenessmonitor-impl&revision=2015-07-06</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: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:alivenessmonitor:impl">prefix:alivenessmonitor-impl</type>
+ <name>alivenessmonitor-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>
+ <rpc-registry>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+ <name>binding-rpc-broker</name>
+ </rpc-registry>
+ <notification-publish-service>
+ <type xmlns:bindingimpl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">bindingimpl:binding-new-notification-publish-service</type>
+ <name>binding-notification-publish-adapter</name>
+ </notification-publish-service>
+ <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>
+ </data>
+ </configuration>
+</snapshot>
\ No newline at end of file
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.alivenessmonitor.internal;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+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.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetNodeconnectorIdFromInterfaceInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetNodeconnectorIdFromInterfaceInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetNodeconnectorIdFromInterfaceOutput;
+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.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+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.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Strings;
+
+abstract class AbstractAlivenessProtocolHandler implements AlivenessProtocolHandler {
+
+ protected ServiceProvider serviceProvider;
+ private InventoryReader inventoryReader;
+
+ public AbstractAlivenessProtocolHandler(ServiceProvider serviceProvider) {
+ this.serviceProvider = serviceProvider;
+ inventoryReader = new InventoryReader(serviceProvider.getDataBroker());
+ }
+
+ private InstanceIdentifier<NodeConnector> getNodeConnectorId(String interfaceName) {
+ InstanceIdentifier<Interface> id = InstanceIdentifier.builder(Interfaces.class)
+ .child(Interface.class, new InterfaceKey(interfaceName)).build();
+
+ Optional<Interface> port = read(LogicalDatastoreType.CONFIGURATION, id);
+ if(port.isPresent()) {
+ NodeConnectorId ncId = getNodeConnectorIdFromInterface(interfaceName);
+ NodeId nodeId = getNodeIdFromNodeConnectorId(ncId);
+
+ InstanceIdentifier<NodeConnector> ncIdentifier =
+ InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, new NodeKey(nodeId))
+ .child(NodeConnector.class, new NodeConnectorKey(ncId)).build();
+ return ncIdentifier;
+ }
+ return null;
+ }
+
+ private NodeConnectorId getNodeConnectorIdFromInterface(String interfaceName) {
+ GetNodeconnectorIdFromInterfaceInput input = new GetNodeconnectorIdFromInterfaceInputBuilder().setIntfName(interfaceName).build();
+ Future<RpcResult<GetNodeconnectorIdFromInterfaceOutput>> output = serviceProvider.getInterfaceManager().getNodeconnectorIdFromInterface(input);
+ RpcResult<GetNodeconnectorIdFromInterfaceOutput> result = null;
+ try {
+ result = output.get();
+ if(result.isSuccessful()) {
+ GetNodeconnectorIdFromInterfaceOutput ncIdOutput = result.getResult();
+ return ncIdOutput.getNodeconnectorId();
+ }
+ } catch(ExecutionException | InterruptedException e) {
+ //TODO: Handle exception
+ }
+
+ return null;
+ }
+
+ private NodeId getNodeIdFromNodeConnectorId(NodeConnectorId ncId) {
+ return new NodeId(ncId.getValue().substring(0,ncId.getValue().lastIndexOf(":")));
+ }
+
+ protected org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceFromOperDS(String interfaceName){
+ InstanceIdentifier.InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> idBuilder =
+ InstanceIdentifier.builder(InterfacesState.class).child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class,
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName));
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> id = idBuilder.build();
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceStateOptional = read(LogicalDatastoreType.OPERATIONAL, id);
+ if(interfaceStateOptional.isPresent()) {
+ return interfaceStateOptional.get();
+ }
+ return null;
+ }
+
+ protected byte[] getMacAddress(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState, String interfaceName) {
+ String macAddress = interfaceState.getPhysAddress().getValue();
+ if(!Strings.isNullOrEmpty(macAddress)) {
+ return AlivenessMonitorUtil.parseMacAddress(macAddress);
+ }
+ return null;
+ }
+
+ private InstanceIdentifier<Interface> getInterfaceIdentifier(InterfaceKey interfaceKey) {
+ InstanceIdentifier.InstanceIdentifierBuilder<Interface> interfaceInstanceIdentifierBuilder =
+ InstanceIdentifier.builder(Interfaces.class).child(Interface.class, interfaceKey);
+ return interfaceInstanceIdentifierBuilder.build();
+ }
+
+ protected Interface getInterfaceFromConfigDS(String interfaceName) {
+ InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
+ InstanceIdentifier<Interface> interfaceId = getInterfaceIdentifier(interfaceKey);
+ Optional<Interface> interfaceOptional = read(LogicalDatastoreType.CONFIGURATION, interfaceId);
+ if (!interfaceOptional.isPresent()) {
+ return null;
+ }
+
+ return interfaceOptional.get();
+ }
+
+
+ private <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path) {
+
+ ReadOnlyTransaction tx = serviceProvider.getDataBroker().newReadOnlyTransaction();
+
+ Optional<T> result = Optional.absent();
+ try {
+ result = tx.read(datastoreType, path).get();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ } finally {
+ tx.close();
+ }
+
+ return result;
+ }
+
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.alivenessmonitor.internal;
+
+import java.lang.Thread.UncaughtExceptionHandler;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+import org.opendaylight.controller.liblldp.NetUtils;
+import org.opendaylight.controller.liblldp.Packet;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.mdsalutil.packet.Ethernet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.EtherTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.LivenessState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorEvent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorEventBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorPauseInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorProfileCreateInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorProfileCreateOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorProfileCreateOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorProfileDeleteInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorStartInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorStartOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorStartOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorStopInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorUnpauseInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitoringMode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorProfileGetInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorProfileGetOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorProfileGetOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629._interface.monitor.map.InterfaceMonitorEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629._interface.monitor.map.InterfaceMonitorEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629._interface.monitor.map.InterfaceMonitorEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.EndpointType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.endpoint.type.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.endpoint.type.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.configs.MonitoringInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.configs.MonitoringInfoBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.event.EventData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.event.EventDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profile.create.input.Profile;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profiles.MonitorProfile;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profiles.MonitorProfileBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.start.input.Config;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitorid.key.map.MonitoridKeyEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitorid.key.map.MonitoridKeyEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitoring.states.MonitoringState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitoring.states.MonitoringStateBuilder;
+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;
+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.idmanager.rev150403.ReleaseIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
+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.PacketProcessingService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.SendToController;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+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 com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.base.Strings;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+
+import static org.opendaylight.vpnservice.alivenessmonitor.internal.AlivenessMonitorUtil.*;
+
+public class AlivenessMonitor implements AlivenessMonitorService, PacketProcessingListener,
+ ServiceProvider, InterfaceStateListener, AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(AlivenessMonitor.class);
+ private final DataBroker broker;
+ private IdManagerService idManager;
+ private PacketProcessingService packetProcessingService;
+ private NotificationPublishService notificationPublishService;
+ private OdlInterfaceRpcService interfaceManager;
+ private Map<Class<?>, AlivenessProtocolHandler> packetTypeToProtocolHandler;
+ private Map<EtherTypes, AlivenessProtocolHandler> ethTypeToProtocolHandler;
+ private ConcurrentMap<Long, ScheduledFuture<?>> monitoringTasks;
+ private LoadingCache<Long, String> monitorIdKeyCache;
+ private ScheduledExecutorService monitorService;
+ private ExecutorService callbackExecutorService;
+
+ private static final int THREAD_POOL_SIZE = 4;
+ private static final boolean INTERRUPT_TASK = true;
+ private static final int NO_DELAY = 0;
+ private static final Long INITIAL_COUNT = 0L;
+ private static final boolean CREATE_MISSING_PARENT = true;
+ private static final int INVALID_ID = 0;
+ private ConcurrentMap<String, Semaphore> lockMap = new ConcurrentHashMap<>();
+
+ private class FutureCallbackImpl implements FutureCallback<Void> {
+ private String message;
+ public FutureCallbackImpl(String message) {
+ this.message = message;
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ LOG.warn("Error in Datastore operation - {}", message, error);
+ }
+
+ @Override
+ public void onSuccess(Void result) {
+ LOG.debug("Success in Datastore operation - {}", message);
+ }
+ }
+
+ private class AlivenessMonitorTask implements Runnable {
+ private MonitoringInfo monitoringInfo;
+
+ public AlivenessMonitorTask(MonitoringInfo monitoringInfo) {
+ this.monitoringInfo = monitoringInfo;
+ }
+
+ @Override
+ public void run() {
+ if(LOG.isTraceEnabled()) {
+ LOG.trace("send monitor packet - {}", monitoringInfo);
+ }
+ sendMonitorPacket(monitoringInfo);
+ }
+ }
+
+ public AlivenessMonitor(DataBroker dataBroker) {
+ broker = dataBroker;
+ ethTypeToProtocolHandler = new EnumMap<>(EtherTypes.class);
+ packetTypeToProtocolHandler = new HashMap<>();
+ monitorService = Executors.newScheduledThreadPool(THREAD_POOL_SIZE,
+ getMonitoringThreadFactory("Aliveness Monitoring Task"));
+ callbackExecutorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE,
+ getMonitoringThreadFactory("Aliveness Callback Handler"));
+ monitoringTasks = new ConcurrentHashMap<>();
+ initilizeCache();
+ }
+
+ private ThreadFactory getMonitoringThreadFactory(String threadNameFormat) {
+ ThreadFactoryBuilder builder = new ThreadFactoryBuilder();
+ builder.setNameFormat(threadNameFormat);
+ builder.setUncaughtExceptionHandler( new UncaughtExceptionHandler() {
+ @Override
+ public void uncaughtException(Thread t, Throwable e) {
+ LOG.error("Received Uncaught Exception event in Thread: {}", t.getName(), e);
+ }
+ });
+ return builder.build();
+ }
+
+ private void initilizeCache() {
+ monitorIdKeyCache = CacheBuilder.newBuilder()
+ .build(new CacheLoader<Long, String>() {
+ @Override
+ public String load(Long monitorId) throws Exception {
+ String monitorKey = null;
+ Optional<MonitoridKeyEntry> optKey = read(LogicalDatastoreType.OPERATIONAL, getMonitorMapId(monitorId));
+ if(optKey.isPresent()) {
+ monitorKey = optKey.get().getMonitorKey();
+ }
+ return monitorKey;
+ }
+ });
+ }
+
+ @Override
+ public void close() throws Exception {
+ monitorIdKeyCache.cleanUp();
+ monitorService.shutdown();
+ callbackExecutorService.shutdown();
+ }
+
+ @Override
+ public DataBroker getDataBroker() {
+ return broker;
+ }
+
+ @Override
+ public OdlInterfaceRpcService getInterfaceManager() {
+ return interfaceManager;
+ }
+
+ public void setPacketProcessingService(PacketProcessingService pktProcessingService) {
+ this.packetProcessingService = pktProcessingService;
+ }
+
+ public void setNotificationPublishService(NotificationPublishService notificationPublishService) {
+ this.notificationPublishService = notificationPublishService;
+ }
+
+ public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
+ this.interfaceManager = interfaceManager;
+ }
+
+ public void setIdManager(IdManagerService idManager) {
+ this.idManager = idManager;
+ createIdPool();
+ }
+
+ public void registerHandler(EtherTypes etherType, AlivenessProtocolHandler protocolHandler) {
+ ethTypeToProtocolHandler.put(etherType, protocolHandler);
+ packetTypeToProtocolHandler.put(protocolHandler.getPacketClass(), protocolHandler);
+ }
+
+ private void createIdPool() {
+ CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
+ .setPoolName(AlivenessMonitorConstants.MONITOR_IDPOOL_NAME)
+ .setLow(AlivenessMonitorConstants.MONITOR_IDPOOL_START)
+ .setHigh(AlivenessMonitorConstants.MONITOR_IDPOOL_SIZE)
+ .build();
+ Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
+ Futures.addCallback(JdkFutureAdapters.listenInPoolThread(result), new FutureCallback<RpcResult<Void>>() {
+
+ @Override
+ public void onFailure(Throwable error) {
+ LOG.error("Failed to create idPool for Aliveness Monitor Service",error);
+ }
+
+ @Override
+ public void onSuccess(RpcResult<Void> result) {
+ if(result.isSuccessful()) {
+ LOG.debug("Created IdPool for Aliveness Monitor Service");
+ } else {
+ LOG.error("RPC to create Idpool failed {}", result.getErrors());
+ }
+ }
+ });
+ }
+
+ private int getUniqueId(final String idKey) {
+ AllocateIdInput getIdInput = new AllocateIdInputBuilder()
+ .setPoolName(AlivenessMonitorConstants.MONITOR_IDPOOL_NAME)
+ .setIdKey(idKey).build();
+
+ Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
+
+ try {
+ RpcResult<AllocateIdOutput> rpcResult = result.get();
+ if(rpcResult.isSuccessful()) {
+ return rpcResult.getResult().getIdValue().intValue();
+ } else {
+ LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when getting Unique Id for key {}", idKey, e);
+ }
+ return INVALID_ID;
+ }
+
+ private void releaseId(String idKey) {
+ ReleaseIdInput idInput = new ReleaseIdInputBuilder()
+ .setPoolName(AlivenessMonitorConstants.MONITOR_IDPOOL_NAME)
+ .setIdKey(idKey).build();
+ try {
+ Future<RpcResult<Void>> result = idManager.releaseId(idInput);
+ RpcResult<Void> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to release Id {} with Key {} returned with Errors {}",
+ idKey, rpcResult.getErrors());
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when releasing Id for key {}", idKey, e);
+ }
+ }
+
+ @Override
+ public void onPacketReceived(PacketReceived packetReceived) {
+ Class<? extends PacketInReason> pktInReason = packetReceived.getPacketInReason();
+ if(LOG.isTraceEnabled()) {
+ LOG.trace("Packet Received {}", packetReceived );
+ }
+
+ if (pktInReason == SendToController.class) {
+ Packet packetInFormatted;
+ byte[] data = packetReceived.getPayload();
+ Ethernet res = new Ethernet();
+ try {
+ packetInFormatted = res.deserialize(data, 0, data.length * NetUtils.NumBitsInAByte);
+ } catch (Exception e) {
+ LOG.warn("Failed to decode packet: {}", e.getMessage());
+ return;
+ }
+
+ if(packetInFormatted == null) {
+ LOG.warn("Failed to deserialize Received Packet from table {}", packetReceived.getTableId().getValue());
+ return;
+ }
+
+ Object objPayload = packetInFormatted.getPayload();
+
+ if(objPayload == null) {
+ LOG.trace("Unsupported packet type. Ignoring the packet...");
+ return;
+ }
+
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("onPacketReceived packet: {}, packet class: {}", packetReceived,
+ objPayload.getClass());
+ }
+
+ AlivenessProtocolHandler livenessProtocolHandler = packetTypeToProtocolHandler.get(objPayload.getClass());
+ if (livenessProtocolHandler == null) {
+ return;
+ }
+
+ String monitorKey = livenessProtocolHandler.handlePacketIn(packetInFormatted.getPayload(), packetReceived);
+
+ if(monitorKey != null) {
+ processReceivedMonitorKey(monitorKey);
+ } else {
+ LOG.debug("No monitorkey associated with received packet");
+ }
+ }
+ }
+
+ private void processReceivedMonitorKey(final String monitorKey) {
+ Preconditions.checkNotNull(monitorKey, "Monitor Key required to process the state");
+
+ LOG.debug("Processing monitorKey: {} for received packet", monitorKey);
+
+ final Semaphore lock = lockMap.get(monitorKey);
+ LOG.debug("Acquiring lock for monitor key : {} to process monitor packet", monitorKey);
+ acquireLock(lock);
+
+ final ReadWriteTransaction tx = broker.newReadWriteTransaction();
+
+ ListenableFuture<Optional<MonitoringState>> stateResult = tx.read(LogicalDatastoreType.OPERATIONAL, getMonitorStateId(monitorKey));
+
+ //READ Callback
+ Futures.addCallback(stateResult, new FutureCallback<Optional<MonitoringState>>() {
+
+ @Override
+ public void onSuccess(Optional<MonitoringState> optState) {
+
+ if(optState.isPresent()) {
+ final MonitoringState currentState = optState.get();
+
+ if(LOG.isTraceEnabled()) {
+ LOG.trace("OnPacketReceived : Monitoring state from ODS : {} ", currentState);
+ }
+
+ Long responsePendingCount = currentState.getResponsePendingCount();
+
+ //Need to relook at the pending count logic to support N out of M scenarios
+// if(currentState.getState() != LivenessState.Up) {
+// //Reset responsePendingCount when state changes from DOWN to UP
+// responsePendingCount = INITIAL_COUNT;
+// }
+//
+// if(responsePendingCount > INITIAL_COUNT) {
+// responsePendingCount = currentState.getResponsePendingCount() - 1;
+// }
+ responsePendingCount = INITIAL_COUNT;
+
+ final boolean stateChanged = (currentState.getState() == LivenessState.Down ||
+ currentState.getState() == LivenessState.Unknown);
+
+ final MonitoringState state = new MonitoringStateBuilder().setMonitorKey(monitorKey).setState(LivenessState.Up)
+ .setResponsePendingCount(responsePendingCount).build();
+ tx.merge(LogicalDatastoreType.OPERATIONAL, getMonitorStateId(monitorKey), state);
+ ListenableFuture<Void> writeResult = tx.submit();
+
+ //WRITE Callback
+ Futures.addCallback(writeResult, new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(Void noarg) {
+ releaseLock(lock);
+ if(stateChanged) {
+ //send notifications
+ LOG.info("Sending notification for monitor Id : {} with Current State: {}",
+ currentState.getMonitorId(), LivenessState.Up);
+ publishNotification(currentState.getMonitorId(), LivenessState.Up);
+ } else {
+ if(LOG.isTraceEnabled()) {
+ LOG.trace("Successful in writing monitoring state {} to ODS", state);
+ }
+ }
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ releaseLock(lock);
+ LOG.warn("Error in writing monitoring state : {} to Datastore", monitorKey, error);
+ if(LOG.isTraceEnabled()) {
+ LOG.trace("Error in writing monitoring state: {} to Datastore", state);
+ }
+ }
+ });
+ } else {
+ LOG.warn("Monitoring State not available for key: {} to process the Packet received", monitorKey);
+ //Complete the transaction
+ tx.submit();
+ releaseLock(lock);
+ }
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ LOG.error("Error when reading Monitoring State for key: {} to process the Packet received", monitorKey, error);
+ //FIXME: Not sure if the transaction status is valid to cancel
+ tx.cancel();
+ releaseLock(lock);
+ }
+ });
+ }
+
+ @Override
+ public PacketProcessingService getPacketProcessingService() {
+ return packetProcessingService;
+ }
+
+ private String getIpAddress(EndpointType endpoint) {
+ String ipAddress = "";
+ if( endpoint instanceof IpAddress) {
+ ipAddress = ((IpAddress) endpoint).getIpAddress().getIpv4Address().getValue();
+ } else if (endpoint instanceof Interface) {
+ ipAddress = ((Interface)endpoint).getInterfaceIp().getIpv4Address().getValue();
+ }
+ return ipAddress;
+ }
+
+ private String getUniqueKey(String interfaceName, String ethType, EndpointType source, EndpointType destination) {
+ StringBuilder builder = new StringBuilder().append(interfaceName).append(AlivenessMonitorConstants.SEPERATOR)
+ .append(ethType);
+ if(source != null) {
+ builder.append(AlivenessMonitorConstants.SEPERATOR).append(getIpAddress(source));
+ }
+
+ if(destination != null) {
+ builder.append(AlivenessMonitorConstants.SEPERATOR).append(getIpAddress(destination));
+ }
+ return builder.toString();
+ }
+
+ @Override
+ public Future<RpcResult<MonitorStartOutput>> monitorStart(MonitorStartInput input) {
+ RpcResultBuilder<MonitorStartOutput> rpcResultBuilder;
+ final Config in = input.getConfig();
+ Long profileId = in.getProfileId();
+ LOG.debug("Monitor Start invoked with Config: {}, Profile Id: {}", in, profileId);
+
+ try {
+ if(in.getMode() != MonitoringMode.OneOne) {
+ throw new UnsupportedConfigException(
+ "Unsupported Monitoring mode. Currently one-one mode is supported");
+ }
+
+ Optional<MonitorProfile> optProfile = read(LogicalDatastoreType.OPERATIONAL, getMonitorProfileId(profileId));
+ final MonitorProfile profile;
+ if(!optProfile.isPresent()) {
+ String errMsg = String.format("No monitoring profile associated with Id: %d", profileId);
+ LOG.error("Monitor start failed. {}", errMsg);
+ throw new RuntimeException(errMsg);
+ } else {
+ profile = optProfile.get();
+ }
+
+ EtherTypes ethType = profile.getProtocolType();
+
+ String interfaceName = null;
+ EndpointType srcEndpointType = in.getSource().getEndpointType();
+
+ if( srcEndpointType instanceof Interface) {
+ Interface endPoint = (Interface) srcEndpointType;
+ interfaceName = endPoint.getInterfaceName();
+ } else {
+ throw new UnsupportedConfigException(
+ "Unsupported source Endpoint type. Only Interface Endpoint currently supported for monitoring");
+ }
+
+ if(Strings.isNullOrEmpty(interfaceName)) {
+ throw new RuntimeException("Interface Name not defined in the source Endpoint");
+ }
+
+ //Initially the support is for one monitoring per interface.
+ //Revisit the retrieving monitor id logic when the multiple monitoring for same interface is needed.
+ EndpointType destEndpointType = null;
+ if(in.getDestination() != null) {
+ destEndpointType = in.getDestination().getEndpointType();
+ }
+ String idKey = getUniqueKey(interfaceName, ethType.toString(), srcEndpointType, destEndpointType);
+ final long monitorId = getUniqueId(idKey);
+ Optional<MonitoringInfo> optKey = read(LogicalDatastoreType.OPERATIONAL, getMonitoringInfoId(monitorId));
+
+ if(optKey.isPresent()) {
+ String message = String.format("Monitoring for the interface %s with this configuration is already registered.", interfaceName);
+ LOG.warn(message);
+ MonitorStartOutput output = new MonitorStartOutputBuilder().setMonitorId(monitorId).build();
+ rpcResultBuilder = RpcResultBuilder.success(output).withWarning(ErrorType.APPLICATION, "config-exists", message);
+ return Futures.immediateFuture(rpcResultBuilder.build());
+ } else {
+ //Construct the monitor key
+ final MonitoringInfo monitoringInfo = new MonitoringInfoBuilder()
+ .setId(monitorId)
+ .setMode(in.getMode())
+ .setProfileId(profileId)
+ .setDestination(in.getDestination())
+ .setSource(in.getSource()).build();
+ //Construct the initial monitor state
+ AlivenessProtocolHandler handler = ethTypeToProtocolHandler.get(ethType);
+ final String monitoringKey = handler.getUniqueMonitoringKey(monitoringInfo);
+
+ MonitoringState monitoringState = new MonitoringStateBuilder()
+ .setMonitorKey(monitoringKey)
+ .setMonitorId(monitorId)
+ .setState(LivenessState.Unknown)
+ .setStatus(MonitorStatus.Started)
+ .setRequestCount(INITIAL_COUNT)
+ .setResponsePendingCount(INITIAL_COUNT).build();
+
+ MonitoridKeyEntry mapEntry = new MonitoridKeyEntryBuilder().setMonitorId(monitorId)
+ .setMonitorKey(monitoringKey).build();
+
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+
+ tx.put(LogicalDatastoreType.OPERATIONAL, getMonitoringInfoId(monitorId), monitoringInfo, CREATE_MISSING_PARENT);
+ LOG.debug("adding oper monitoring info {}", monitoringInfo);
+
+ tx.put(LogicalDatastoreType.OPERATIONAL, getMonitorStateId(monitoringKey), monitoringState, CREATE_MISSING_PARENT);
+ LOG.debug("adding oper monitoring state {}", monitoringState);
+
+ tx.put(LogicalDatastoreType.OPERATIONAL, getMonitorMapId(monitorId), mapEntry, CREATE_MISSING_PARENT);
+ LOG.debug("adding oper map entry {}", mapEntry);
+
+ Futures.addCallback(tx.submit(), new FutureCallback<Void>() {
+ @Override
+ public void onFailure(Throwable error) {
+ String errorMsg = String.format("Adding Monitoring info: %s in Datastore failed", monitoringInfo);
+ LOG.warn(errorMsg, error);
+ throw new RuntimeException(errorMsg, error);
+ }
+
+ @Override
+ public void onSuccess(Void noarg) {
+ //Schedule task
+ LOG.debug("Scheduling monitor task for config: {}", in);
+ scheduleMonitoringTask(monitoringInfo, profile.getMonitorInterval());
+ lockMap.put(monitoringKey, new Semaphore(1, true));
+ }
+ });
+ }
+
+ associateMonitorIdWithInterface(monitorId, interfaceName);
+
+ MonitorStartOutput output = new MonitorStartOutputBuilder()
+ .setMonitorId(monitorId).build();
+
+ rpcResultBuilder = RpcResultBuilder.success(output);
+ } catch(Exception e) {
+ LOG.error("Start Monitoring Failed. {}", e.getMessage(), e);
+ rpcResultBuilder = RpcResultBuilder.<MonitorStartOutput>failed().withError(ErrorType.APPLICATION, e.getMessage(), e);
+ }
+ return Futures.immediateFuture(rpcResultBuilder.build());
+ }
+
+ private void associateMonitorIdWithInterface(final Long monitorId, final String interfaceName) {
+ LOG.debug("associate monitor Id {} with interface {}", monitorId, interfaceName);
+ final ReadWriteTransaction tx = broker.newReadWriteTransaction();
+ ListenableFuture<Optional<InterfaceMonitorEntry>> readFuture =
+ tx.read(LogicalDatastoreType.OPERATIONAL, getInterfaceMonitorMapId(interfaceName));
+ ListenableFuture<Void> updateFuture =
+ Futures.transform(readFuture, new AsyncFunction<Optional<InterfaceMonitorEntry>, Void>() {
+
+ @Override
+ public ListenableFuture<Void> apply(Optional<InterfaceMonitorEntry> optEntry) throws Exception {
+ if(optEntry.isPresent()) {
+ InterfaceMonitorEntry entry = optEntry.get();
+ List<Long> monitorIds = entry.getMonitorIds();
+ monitorIds.add(monitorId);
+ InterfaceMonitorEntry newEntry = new InterfaceMonitorEntryBuilder()
+ .setKey(new InterfaceMonitorEntryKey(interfaceName)).setMonitorIds(monitorIds).build();
+ tx.merge(LogicalDatastoreType.OPERATIONAL, getInterfaceMonitorMapId(interfaceName), newEntry);
+ } else {
+ //Create new monitor entry
+ LOG.debug("Adding new interface-monitor association for interface {} with id {}", interfaceName, monitorId);
+ List<Long> monitorIds = new ArrayList<>();
+ monitorIds.add(monitorId);
+ InterfaceMonitorEntry newEntry =
+ new InterfaceMonitorEntryBuilder().setInterfaceName(interfaceName).setMonitorIds(monitorIds).build();
+ tx.put(LogicalDatastoreType.OPERATIONAL,
+ getInterfaceMonitorMapId(interfaceName), newEntry, CREATE_MISSING_PARENT);
+ }
+ return tx.submit();
+ }
+ });
+
+ Futures.addCallback(updateFuture, new FutureCallbackImpl(
+ String.format("Association of monitorId %d with Interface %s", monitorId, interfaceName)));
+ }
+
+ private void scheduleMonitoringTask(MonitoringInfo monitoringInfo, long monitorInterval) {
+ AlivenessMonitorTask monitorTask = new AlivenessMonitorTask(monitoringInfo);
+ ScheduledFuture<?> scheduledFutureResult = monitorService.scheduleAtFixedRate(
+ monitorTask, NO_DELAY, monitorInterval, TimeUnit.MILLISECONDS);
+ monitoringTasks.put(monitoringInfo.getId(), scheduledFutureResult);
+ }
+
+ @Override
+ public Future<RpcResult<Void>> monitorPause(MonitorPauseInput input) {
+ LOG.debug("Monitor Pause operation invoked for monitor id: {}", input.getMonitorId());
+ SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+ final Long monitorId = input.getMonitorId();
+
+ //Set the monitoring status to Paused
+ updateMonitorStatusTo(monitorId, MonitorStatus.Paused, new Predicate<MonitorStatus>() {
+ @Override
+ public boolean apply(MonitorStatus currentStatus) {
+ return currentStatus == MonitorStatus.Started;
+ }
+ });
+
+ if(stopMonitoringTask(monitorId)) {
+ result.set(RpcResultBuilder.<Void>success().build());
+ } else {
+ String errorMsg = String.format("No Monitoring Task availble to pause for the given monitor id : %d", monitorId);
+ LOG.error("Monitor Pause operation failed- {}",errorMsg);
+ result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, errorMsg).build());
+ }
+
+ return result;
+ }
+
+ @Override
+ public Future<RpcResult<Void>> monitorUnpause(MonitorUnpauseInput input) {
+ LOG.debug("Monitor Unpause operation invoked for monitor id: {}", input.getMonitorId());
+ final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+
+ final Long monitorId = input.getMonitorId();
+ final ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
+ ListenableFuture<Optional<MonitoringInfo>> readInfoResult =
+ tx.read(LogicalDatastoreType.OPERATIONAL, getMonitoringInfoId(monitorId));
+
+ Futures.addCallback(readInfoResult, new FutureCallback<Optional<MonitoringInfo>>() {
+
+ @Override
+ public void onFailure(Throwable error) {
+ String msg = String.format("Unable to read monitoring info associated with monitor id %d", monitorId);
+ LOG.error("Monitor unpause Failed. {}", msg, error);
+ result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, msg, error).build());
+ }
+
+ @Override
+ public void onSuccess(Optional<MonitoringInfo> optInfo) {
+ if(optInfo.isPresent()) {
+ final MonitoringInfo info = optInfo.get();
+ ListenableFuture<Optional<MonitorProfile>> readProfile =
+ tx.read(LogicalDatastoreType.OPERATIONAL, getMonitorProfileId(info.getProfileId()));
+ Futures.addCallback(readProfile, new FutureCallback<Optional<MonitorProfile>>(){
+
+ @Override
+ public void onFailure(Throwable error) {
+ String msg = String.format("Unable to read Monitoring profile associated with id %d", info.getProfileId());
+ LOG.warn("Monitor unpause Failed. {}", msg, error);
+ result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, msg, error).build());
+ }
+
+ @Override
+ public void onSuccess(Optional<MonitorProfile> optProfile) {
+ tx.close();
+ if(optProfile.isPresent()) {
+ updateMonitorStatusTo(monitorId, MonitorStatus.Started, new Predicate<MonitorStatus>() {
+ @Override
+ public boolean apply(MonitorStatus currentStatus) {
+ return (currentStatus == MonitorStatus.Paused ||
+ currentStatus == MonitorStatus.Stopped);
+ }
+ });
+ MonitorProfile profile = optProfile.get();
+ LOG.debug("Monitor Resume - Scheduling monitoring task with Id: {}", monitorId);
+ scheduleMonitoringTask(info, profile.getMonitorInterval());
+ result.set(RpcResultBuilder.<Void>success().build());
+ } else {
+ String msg = String.format("Monitoring profile associated with id %d is not present", info.getProfileId());
+ LOG.warn("Monitor unpause Failed. {}", msg);
+ result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, msg).build());
+ }
+ }
+ });
+ } else {
+ tx.close();
+ String msg = String.format("Monitoring info associated with id %d is not present", monitorId);
+ LOG.warn("Monitor unpause Failed. {}", msg);
+ result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, msg).build());
+ }
+ }
+ }, callbackExecutorService);
+
+ return result;
+ }
+
+ private boolean stopMonitoringTask(Long monitorId) {
+ return stopMonitoringTask(monitorId, INTERRUPT_TASK);
+ }
+
+ private boolean stopMonitoringTask(Long monitorId, boolean interruptTask) {
+ ScheduledFuture<?> scheduledFutureResult = monitoringTasks.get(monitorId);
+ if(scheduledFutureResult != null) {
+ scheduledFutureResult.cancel(interruptTask);
+ return true;
+ }
+ return false;
+ }
+
+ private Optional<MonitorProfile> getMonitorProfile(Long profileId) {
+ return read(LogicalDatastoreType.OPERATIONAL, getMonitorProfileId(profileId));
+ }
+
+ private void acquireLock(Semaphore lock) {
+ if(lock == null) {
+ return;
+ }
+
+ boolean acquiredLock = false;
+ try {
+ acquiredLock = lock.tryAcquire(50, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ LOG.warn("Thread interrupted when waiting to acquire the lock");
+ }
+
+ if(!acquiredLock) {
+ LOG.warn("Previous transaction did not complete in time. Releasing the lock to proceed");
+ lock.release();
+ try {
+ lock.acquire();
+ LOG.trace("Lock acquired successfully");
+ } catch (InterruptedException e) {
+ LOG.warn("Acquire failed");
+ }
+ } else {
+ LOG.trace("Lock acquired successfully");
+ }
+ }
+
+ private void releaseLock(Semaphore lock) {
+ if(lock != null) {
+ lock.release();
+ }
+ }
+
+ private void sendMonitorPacket(final MonitoringInfo monitoringInfo) {
+ //TODO: Handle interrupts
+ final Long monitorId = monitoringInfo.getId();
+ final String monitorKey = monitorIdKeyCache.getUnchecked(monitorId);
+ if(monitorKey == null) {
+ LOG.warn("No monitor Key associated with id {} to send the monitor packet", monitorId);
+ return;
+ } else {
+ LOG.debug("Sending monitoring packet for key: {}", monitorKey);
+ }
+
+ final MonitorProfile profile;
+ Optional<MonitorProfile> optProfile = getMonitorProfile(monitoringInfo.getProfileId());
+ if(optProfile.isPresent()) {
+ profile = optProfile.get();
+ } else {
+ LOG.warn("No monitor profile associated with id {}. "
+ + "Could not send Monitor packet for monitor-id {}", monitoringInfo.getProfileId(), monitorId);
+ return;
+ }
+
+ final Semaphore lock = lockMap.get(monitorKey);
+ LOG.debug("Acquiring lock for monitor key : {} to send monitor packet", monitorKey);
+ acquireLock(lock);
+
+ final ReadWriteTransaction tx = broker.newReadWriteTransaction();
+ ListenableFuture<Optional<MonitoringState>> readResult =
+ tx.read(LogicalDatastoreType.OPERATIONAL, getMonitorStateId(monitorKey));
+ ListenableFuture<Void> writeResult = Futures.transform(readResult, new AsyncFunction<Optional<MonitoringState>, Void>() {
+
+ @Override
+ public ListenableFuture<Void> apply(Optional<MonitoringState> optState)
+ throws Exception {
+ if(optState.isPresent()) {
+ MonitoringState state = optState.get();
+
+ //Increase the request count
+ Long requestCount = state.getRequestCount() + 1;
+
+ //Check with the monitor window
+ LivenessState currentLivenessState = state.getState();
+
+ //Increase the pending response count
+ long responsePendingCount = state.getResponsePendingCount();
+ if(responsePendingCount < profile.getMonitorWindow()) {
+ responsePendingCount = responsePendingCount + 1;
+ }
+
+ //Check with the failure thresold
+ if(responsePendingCount >= profile.getFailureThreshold()) {
+ //Change the state to down and notify
+ if(currentLivenessState != LivenessState.Down) {
+ LOG.debug("Response pending Count: {}, Failure threshold: {} for monitorId {}",
+ responsePendingCount, profile.getFailureThreshold(), state.getMonitorId());
+ LOG.info("Sending notification for monitor Id : {} with State: {}",
+ state.getMonitorId(), LivenessState.Down);
+ publishNotification(monitorId, LivenessState.Down);
+ currentLivenessState = LivenessState.Down;
+ //Reset requestCount when state changes from UP to DOWN
+ requestCount = INITIAL_COUNT;
+ }
+ }
+
+ //Update the ODS with state
+ MonitoringState updatedState = new MonitoringStateBuilder(/*state*/).setMonitorKey(state.getMonitorKey())
+ .setRequestCount(requestCount)
+ .setResponsePendingCount(responsePendingCount)
+ .setState(currentLivenessState).build();
+ tx.merge(LogicalDatastoreType.OPERATIONAL, getMonitorStateId(state.getMonitorKey()), updatedState);
+ return tx.submit();
+ } else {
+ //Close the transaction
+ tx.submit();
+ String errorMsg = String.format("Monitoring State associated with id %d is not present to send packet out.", monitorId);
+ return Futures.immediateFailedFuture(new RuntimeException(errorMsg));
+ }
+ }
+
+ });
+
+ Futures.addCallback(writeResult, new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(Void noarg) {
+ //invoke packetout on protocol handler
+ AlivenessProtocolHandler handler = ethTypeToProtocolHandler.get(profile.getProtocolType());
+ if(handler != null) {
+ LOG.debug("Sending monitoring packet {}", monitoringInfo);
+ handler.sendPacketOut(monitoringInfo);
+ }
+ releaseLock(lock);
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ LOG.warn("Updating monitoring state for key: {} failed. Monitoring packet is not sent", monitorKey, error);
+ releaseLock(lock);
+ }
+
+ });
+
+ }
+
+ private void publishNotification(final Long monitorId, final LivenessState state) {
+ LOG.debug("Sending notification for id {} - state {}", monitorId, state);
+ EventData data = new EventDataBuilder().setMonitorId(monitorId)
+ .setMonitorState(state).build();
+ MonitorEvent event = new MonitorEventBuilder().setEventData(data).build();;
+ final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
+ Futures.addCallback(eventFuture, new FutureCallback<Object>() {
+ @Override
+ public void onFailure(Throwable error) {
+ LOG.warn("Error in notifying listeners for id {} - state {}", monitorId, state, error);
+ }
+
+ @Override
+ public void onSuccess(Object arg) {
+ LOG.trace("Successful in notifying listeners for id {} - state {}", monitorId, state);
+ }
+ });
+ }
+
+ @Override
+ public Future<RpcResult<MonitorProfileCreateOutput>> monitorProfileCreate(final MonitorProfileCreateInput input) {
+ LOG.debug("Monitor Profile Create operation - {}", input.getProfile());
+ final SettableFuture<RpcResult<MonitorProfileCreateOutput>> result = SettableFuture.create();
+ Profile profile = input.getProfile();
+ final Long failureThreshold = profile.getFailureThreshold();
+ final Long monitorInterval = profile.getMonitorInterval();
+ final Long monitorWindow = profile.getMonitorWindow();
+ final EtherTypes ethType = profile.getProtocolType();
+ String idKey = getUniqueProfileKey(failureThreshold, monitorInterval, monitorWindow, ethType);
+ final Long profileId = Long.valueOf(getUniqueId(idKey));
+
+ final ReadWriteTransaction tx = broker.newReadWriteTransaction();
+ ListenableFuture<Optional<MonitorProfile>> readFuture =
+ tx.read(LogicalDatastoreType.OPERATIONAL, getMonitorProfileId(profileId));
+ ListenableFuture<RpcResult<MonitorProfileCreateOutput>> resultFuture =
+ Futures.transform(readFuture, new AsyncFunction<Optional<MonitorProfile>, RpcResult<MonitorProfileCreateOutput>>() {
+
+ @Override
+ public ListenableFuture<RpcResult<MonitorProfileCreateOutput>> apply(
+ Optional<MonitorProfile> optProfile) throws Exception {
+ if(optProfile.isPresent()) {
+ tx.cancel();
+ MonitorProfileCreateOutput output = new MonitorProfileCreateOutputBuilder()
+ .setProfileId(profileId).build();
+ String msg = String.format("Monitor profile %s already present for the given input", input);
+ LOG.warn(msg);
+ result.set(RpcResultBuilder.success(output)
+ .withWarning(ErrorType.PROTOCOL, "profile-exists", msg).build());
+ } else {
+ final MonitorProfile monitorProfile = new MonitorProfileBuilder().setId(profileId)
+ .setFailureThreshold(failureThreshold)
+ .setMonitorInterval(monitorInterval)
+ .setMonitorWindow(monitorWindow)
+ .setProtocolType(ethType).build();
+ tx.put(LogicalDatastoreType.OPERATIONAL, getMonitorProfileId(profileId), monitorProfile, CREATE_MISSING_PARENT);
+ Futures.addCallback(tx.submit(), new FutureCallback<Void>() {
+ @Override
+ public void onFailure(Throwable error) {
+ String msg =
+ String.format("Error when storing monitorprofile %s in datastore", monitorProfile);
+ LOG.error(msg, error);
+ result.set(RpcResultBuilder.<MonitorProfileCreateOutput>failed()
+ .withError(ErrorType.APPLICATION, msg, error).build());
+ }
+ @Override
+ public void onSuccess(Void noarg) {
+ MonitorProfileCreateOutput output = new MonitorProfileCreateOutputBuilder()
+ .setProfileId(profileId).build();
+ result.set(RpcResultBuilder.success(output).build());
+ }
+ });
+ }
+ return result;
+ }
+ }, callbackExecutorService);
+ Futures.addCallback(resultFuture, new FutureCallback<RpcResult<MonitorProfileCreateOutput>>() {
+ @Override
+ public void onFailure(Throwable error) {
+ //This would happen when any error happens during reading for monitoring profile
+ String msg = String.format("Error in creating monitorprofile - %s", input);
+ result.set(RpcResultBuilder.<MonitorProfileCreateOutput>failed()
+ .withError(ErrorType.APPLICATION, msg, error).build());
+ LOG.error(msg, error);
+ }
+
+ @Override
+ public void onSuccess(RpcResult<MonitorProfileCreateOutput> result) {
+ LOG.debug("Successfully created monitor Profile {} ", input);
+ }
+ }, callbackExecutorService);
+ return result;
+ }
+
+
+ @Override
+ public Future<RpcResult<MonitorProfileGetOutput>> monitorProfileGet(MonitorProfileGetInput input){
+ LOG.debug("Monitor Profile Get operation for input profile- {}", input.getProfile());
+ RpcResultBuilder<MonitorProfileGetOutput> rpcResultBuilder;
+ try{
+ final Long profileId = getExistingProfileId(input);
+
+ MonitorProfileGetOutputBuilder output = new MonitorProfileGetOutputBuilder().setProfileId(profileId);
+ rpcResultBuilder = RpcResultBuilder.success();
+ rpcResultBuilder.withResult(output.build());
+ }catch(Exception e){
+ LOG.error("Retrieval of monitor profile ID for input {} failed due to {}" , input, e);
+ rpcResultBuilder = RpcResultBuilder.failed();
+ }
+ return Futures.immediateFuture(rpcResultBuilder.build());
+ }
+
+ private Long getExistingProfileId(MonitorProfileGetInput input){
+ org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profile.get.input.Profile profile = input.getProfile();
+ final Long failureThreshold = profile.getFailureThreshold();
+ final Long monitorInterval = profile.getMonitorInterval();
+ final Long monitorWindow = profile.getMonitorWindow();
+ final EtherTypes ethType = profile.getProtocolType();
+ LOG.debug("getExistingProfileId for profile : {}", input.getProfile());
+ String idKey = getUniqueProfileKey(failureThreshold, monitorInterval, monitorWindow, ethType);
+ LOG.debug("Obtained existing profile ID for profile : {}", input.getProfile());
+ return (Long.valueOf(getUniqueId(idKey)));
+ }
+
+ private String getUniqueProfileKey(Long failureThreshold,Long monitorInterval,Long monitorWindow,EtherTypes ethType) {
+ return new StringBuilder().append(failureThreshold).append(AlivenessMonitorConstants.SEPERATOR)
+ .append(monitorInterval).append(AlivenessMonitorConstants.SEPERATOR)
+ .append(monitorWindow).append(AlivenessMonitorConstants.SEPERATOR)
+ .append(ethType).append(AlivenessMonitorConstants.SEPERATOR).toString();
+ }
+
+ @Override
+ public Future<RpcResult<Void>> monitorProfileDelete(final MonitorProfileDeleteInput input) {
+ LOG.debug("Monitor Profile delete for Id: {}", input.getProfileId());
+ final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+ final Long profileId = input.getProfileId();
+ final ReadWriteTransaction tx = broker.newReadWriteTransaction();
+ ListenableFuture<Optional<MonitorProfile>> readFuture =
+ tx.read(LogicalDatastoreType.OPERATIONAL, getMonitorProfileId(profileId));
+ ListenableFuture<RpcResult<Void>> writeFuture =
+ Futures.transform(readFuture, new AsyncFunction<Optional<MonitorProfile>, RpcResult<Void>>() {
+
+ @Override
+ public ListenableFuture<RpcResult<Void>> apply(final Optional<MonitorProfile> optProfile) throws Exception {
+ if(optProfile.isPresent()) {
+ tx.delete(LogicalDatastoreType.OPERATIONAL, getMonitorProfileId(profileId));
+ Futures.addCallback(tx.submit(), new FutureCallback<Void>() {
+ @Override
+ public void onFailure(Throwable error) {
+ String msg = String.format("Error when removing monitor profile %d from datastore", profileId);
+ LOG.error(msg, error);
+ result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, msg, error).build());
+ }
+
+ @Override
+ public void onSuccess(Void noarg) {
+ MonitorProfile profile = optProfile.get();
+ String id = getUniqueProfileKey(profile.getFailureThreshold(), profile.getMonitorInterval(),
+ profile.getMonitorWindow(), profile.getProtocolType());
+ releaseId(id);
+ result.set(RpcResultBuilder.<Void>success().build());
+ }
+ });
+ } else {
+ String msg = String.format("Monitor profile with Id: %d does not exist", profileId);
+ LOG.info(msg);
+ result.set(RpcResultBuilder.<Void>success().withWarning(ErrorType.PROTOCOL, "invalid-value", msg).build());
+ }
+ return result;
+ }
+ }, callbackExecutorService);
+
+ Futures.addCallback(writeFuture, new FutureCallback<RpcResult<Void>>() {
+
+ @Override
+ public void onFailure(Throwable error) {
+ String msg = String.format("Error when removing monitor profile %d from datastore", profileId);
+ LOG.error(msg, error);
+ result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, msg, error).build());
+ }
+
+ @Override
+ public void onSuccess(RpcResult<Void> noarg) {
+ LOG.debug("Successfully removed Monitor Profile {}", profileId);
+ }
+ }, callbackExecutorService);
+ return result;
+ }
+
+ @Override
+ public Future<RpcResult<Void>> monitorStop(MonitorStopInput input) {
+ LOG.debug("Monitor Stop operation for monitor id - {}", input.getMonitorId());
+ SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+
+ final Long monitorId = input.getMonitorId();
+ Optional<MonitoringInfo> optInfo = read(LogicalDatastoreType.OPERATIONAL, getMonitoringInfoId(monitorId));
+ if(optInfo.isPresent()) {
+ //Stop the monitoring task
+ stopMonitoringTask(monitorId);
+
+ //Cleanup the Data store
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ String monitorKey = monitorIdKeyCache.getUnchecked(monitorId);
+ if(monitorKey != null) {
+ tx.delete(LogicalDatastoreType.OPERATIONAL, getMonitorStateId(monitorKey));
+ monitorIdKeyCache.invalidate(monitorId);
+ }
+
+ tx.delete(LogicalDatastoreType.OPERATIONAL, getMonitoringInfoId(monitorId));
+ Futures.addCallback(tx.submit(),
+ new FutureCallbackImpl(String.format("Delete monitor state with Id %d", monitorId)));
+
+ MonitoringInfo info = optInfo.get();
+ String interfaceName = getInterfaceName(info.getSource().getEndpointType());
+ if(interfaceName != null) {
+ removeMonitorIdFromInterfaceAssociation(monitorId, interfaceName);
+ }
+ releaseIdForMonitoringInfo(info);
+
+ lockMap.remove(monitorKey);
+
+ result.set(RpcResultBuilder.<Void>success().build());
+ } else {
+ String errorMsg = String.format("Do not have monitoring information associated with key %d", monitorId);
+ LOG.error("Delete monitoring operation Failed - {}", errorMsg);
+ result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, errorMsg).build());
+ }
+
+ return result;
+ }
+
+ private void removeMonitorIdFromInterfaceAssociation(final Long monitorId, final String interfaceName) {
+ LOG.debug("Remove monitorId {} from Interface association {}", monitorId, interfaceName);
+ final ReadWriteTransaction tx = broker.newReadWriteTransaction();
+ ListenableFuture<Optional<InterfaceMonitorEntry>> readFuture = tx.read(LogicalDatastoreType.OPERATIONAL, getInterfaceMonitorMapId(interfaceName));
+ ListenableFuture<Void> updateFuture = Futures.transform(readFuture, new AsyncFunction<Optional<InterfaceMonitorEntry>, Void>() {
+
+ @Override
+ public ListenableFuture<Void> apply(Optional<InterfaceMonitorEntry> optEntry) throws Exception {
+ if(optEntry.isPresent()) {
+ InterfaceMonitorEntry entry = optEntry.get();
+ List<Long> monitorIds = entry.getMonitorIds();
+ monitorIds.remove(monitorId);
+ InterfaceMonitorEntry newEntry = new InterfaceMonitorEntryBuilder(entry)
+ .setKey(new InterfaceMonitorEntryKey(interfaceName)).setMonitorIds(monitorIds).build();
+ tx.put(LogicalDatastoreType.OPERATIONAL, getInterfaceMonitorMapId(interfaceName), newEntry, CREATE_MISSING_PARENT);
+ return tx.submit();
+ } else {
+ LOG.warn("No Interface map entry found {} to remove monitorId {}", interfaceName, monitorId);
+ tx.cancel();
+ return Futures.immediateFuture(null);
+ }
+ }
+ });
+
+ Futures.addCallback(updateFuture, new FutureCallbackImpl(
+ String.format("Dis-association of monitorId %d with Interface %s", monitorId, interfaceName)));
+ }
+
+
+ private void releaseIdForMonitoringInfo(MonitoringInfo info) {
+ Long monitorId = info.getId();
+ EndpointType source = info.getSource().getEndpointType();
+ String interfaceName = getInterfaceName(source);
+ if(!Strings.isNullOrEmpty(interfaceName)) {
+ Optional<MonitorProfile> optProfile = read(LogicalDatastoreType.OPERATIONAL, getMonitorProfileId(info.getProfileId()));
+ if(optProfile.isPresent()) {
+ EtherTypes ethType = optProfile.get().getProtocolType();
+ EndpointType destination = (info.getDestination() != null) ? info.getDestination().getEndpointType() : null;
+ String idKey = getUniqueKey(interfaceName, ethType.toString(), source, destination);
+ releaseId(idKey);
+ } else {
+ LOG.warn("Could not release monitorId {}. No profile associated with it", monitorId);
+ }
+ }
+ }
+
+ private String getInterfaceName(EndpointType endpoint) {
+ String interfaceName = null;
+ if(endpoint instanceof Interface) {
+ interfaceName = ((Interface)endpoint).getInterfaceName();
+ }
+ return interfaceName;
+ }
+
+ private void stopMonitoring(long monitorId) {
+ updateMonitorStatusTo(monitorId, MonitorStatus.Stopped, new Predicate<MonitorStatus>() {
+ @Override
+ public boolean apply(MonitorStatus currentStatus) {
+ return currentStatus != MonitorStatus.Stopped;
+ }
+ });
+ if(!stopMonitoringTask(monitorId)) {
+ LOG.warn("No monitoring task running to perform cancel operation for monitorId {}", monitorId);
+ }
+ }
+
+ private void updateMonitorStatusTo(final Long monitorId, final MonitorStatus newStatus, final Predicate<MonitorStatus> isValidStatus) {
+ final String monitorKey = monitorIdKeyCache.getUnchecked(monitorId);
+ if(monitorKey == null) {
+ LOG.warn("No monitor Key associated with id {} to change the monitor status to {}", monitorId, newStatus);
+ return;
+ }
+ final ReadWriteTransaction tx = broker.newReadWriteTransaction();
+
+ ListenableFuture<Optional<MonitoringState>> readResult =
+ tx.read(LogicalDatastoreType.OPERATIONAL, getMonitorStateId(monitorKey));
+
+ ListenableFuture<Void> writeResult = Futures.transform(readResult, new AsyncFunction<Optional<MonitoringState>, Void>() {
+ @Override
+ public ListenableFuture<Void> apply(Optional<MonitoringState> optState) throws Exception {
+ if(optState.isPresent()) {
+ MonitoringState state = optState.get();
+ if(isValidStatus.apply(state.getStatus())) {
+ MonitoringState updatedState = new MonitoringStateBuilder().setMonitorKey(monitorKey)
+ .setStatus(newStatus).build();
+ tx.merge(LogicalDatastoreType.OPERATIONAL, getMonitorStateId(monitorKey), updatedState);
+ } else {
+ LOG.warn("Invalid Monitoring status {}, cannot be updated to {} for monitorId {}"
+ , state.getStatus(), newStatus, monitorId);
+ }
+ } else {
+ LOG.warn("No associated monitoring state data available to update the status to {} for {}", newStatus, monitorId);
+ }
+ return tx.submit();
+ }
+ });
+
+ Futures.addCallback(writeResult,
+ new FutureCallbackImpl(String.format("Monitor status update for %d to %s", monitorId, newStatus.toString())));
+ }
+
+ private void resumeMonitoring(final long monitorId) {
+ final ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
+ ListenableFuture<Optional<MonitoringInfo>> readInfoResult =
+ tx.read(LogicalDatastoreType.OPERATIONAL, getMonitoringInfoId(monitorId));
+
+ Futures.addCallback(readInfoResult, new FutureCallback<Optional<MonitoringInfo>>() {
+
+ @Override
+ public void onFailure(Throwable error) {
+ String msg = String.format("Unable to read monitoring info associated with monitor id %d", monitorId);
+ LOG.error("Monitor resume Failed. {}", msg, error);
+ }
+
+ @Override
+ public void onSuccess(Optional<MonitoringInfo> optInfo) {
+ if(optInfo.isPresent()) {
+ final MonitoringInfo info = optInfo.get();
+ ListenableFuture<Optional<MonitorProfile>> readProfile =
+ tx.read(LogicalDatastoreType.OPERATIONAL, getMonitorProfileId(info.getProfileId()));
+ Futures.addCallback(readProfile, new FutureCallback<Optional<MonitorProfile>>(){
+
+ @Override
+ public void onFailure(Throwable error) {
+ String msg = String.format("Unable to read Monitoring profile associated with id %d", info.getProfileId());
+ LOG.warn("Monitor resume Failed. {}", msg, error);
+ }
+
+ @Override
+ public void onSuccess(Optional<MonitorProfile> optProfile) {
+ tx.close();
+ if(optProfile.isPresent()) {
+ updateMonitorStatusTo(monitorId, MonitorStatus.Started, new Predicate<MonitorStatus>() {
+ @Override
+ public boolean apply(MonitorStatus currentStatus) {
+ return currentStatus != MonitorStatus.Started;
+ }
+ });
+ MonitorProfile profile = optProfile.get();
+ LOG.debug("Monitor Resume - Scheduling monitoring task for Id: {}", monitorId);
+ scheduleMonitoringTask(info, profile.getMonitorInterval());
+ } else {
+ String msg = String.format("Monitoring profile associated with id %d is not present", info.getProfileId());
+ LOG.warn("Monitor resume Failed. {}", msg);
+ }
+ }
+ });
+ } else {
+ tx.close();
+ String msg = String.format("Monitoring info associated with id %d is not present", monitorId);
+ LOG.warn("Monitor resume Failed. {}", msg);
+ }
+ }
+ });
+ }
+
+ //DATA STORE OPERATIONS
+ private <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
+ ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
+
+ Optional<T> result = Optional.absent();
+ try {
+ result = tx.read(datastoreType, path).get();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Error reading data from path {} in datastore {}", path, datastoreType, e);
+ } finally {
+ tx.close();
+ }
+
+ return result;
+ }
+
+ @Override
+ public void onInterfaceStateUp(String interfaceName) {
+ List<Long> monitorIds = getMonitorIds(interfaceName);
+ if(monitorIds.isEmpty()) {
+ LOG.warn("Could not get monitorId for interface: {}", interfaceName);
+ return;
+ }
+ for(Long monitorId : monitorIds) {
+ LOG.debug("Resume monitoring on interface: {} with monitorId: {}", interfaceName, monitorId);
+ resumeMonitoring(monitorId);
+ }
+ }
+
+ @Override
+ public void onInterfaceStateDown(String interfaceName) {
+ List<Long> monitorIds = getMonitorIds(interfaceName);
+ if(monitorIds.isEmpty()) {
+ LOG.warn("Could not get monitorIds for interface: {}", interfaceName);
+ return;
+ }
+ for(Long monitorId : monitorIds) {
+ LOG.debug("Suspend monitoring on interface: {} with monitorId: {}", interfaceName, monitorId);
+ stopMonitoring(monitorId);
+ }
+ }
+
+ private List<Long> getMonitorIds(String interfaceName) {
+ Optional<InterfaceMonitorEntry> optEntry = read(LogicalDatastoreType.OPERATIONAL,
+ getInterfaceMonitorMapId(interfaceName));
+ if(optEntry.isPresent()) {
+ InterfaceMonitorEntry entry = optEntry.get();
+ return entry.getMonitorIds();
+ }
+ return Collections.emptyList();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.alivenessmonitor.internal;
+
+public class AlivenessMonitorConstants {
+ static final String MONITOR_IDPOOL_NAME = "aliveness-monitor";
+ static final long MONITOR_IDPOOL_START = 1L;
+ static final long MONITOR_IDPOOL_SIZE = 65535;
+ static final short L3_INTERFACE_TABLE = 80;
+ static final String SEPERATOR = ".";
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.alivenessmonitor.internal;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.controller.md.sal.binding.api.NotificationService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.EtherTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilService;
+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.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AlivenessMonitorProvider implements BindingAwareProvider,
+ AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(AlivenessMonitorProvider.class);
+ private AlivenessMonitor alivenessMonitor;
+ private RpcProviderRegistry rpcProviderRegistry;
+ private OdlInterfaceRpcService interfaceManager;
+ private RpcRegistration<AlivenessMonitorService> rpcRegistration;
+ private ListenerRegistration<AlivenessMonitor> listenerRegistration;
+ private NotificationService notificationService;
+ private NotificationPublishService notificationPublishService;
+
+ public AlivenessMonitorProvider(RpcProviderRegistry rpcProviderRegistry) {
+ this.rpcProviderRegistry = rpcProviderRegistry;
+ }
+
+ public RpcProviderRegistry getRpcProviderRegistry() {
+ return rpcProviderRegistry;
+ }
+
+ public void setNotificationService(NotificationService notificationService) {
+ this.notificationService = notificationService;
+ }
+
+ public void setNotificationPublishService(NotificationPublishService notificationPublishService) {
+ this.notificationPublishService = notificationPublishService;
+ }
+
+ @Override
+ public void close() throws Exception {
+ rpcRegistration.close();
+ listenerRegistration.close();
+ alivenessMonitor.close();
+ }
+
+ @Override
+ public void onSessionInitiated(ProviderContext session) {
+ LOG.info("AlivenessMonitorProvider Session Initiated");
+ try {
+ final DataBroker dataBroker = session.getSALService(DataBroker.class);
+ PacketProcessingService pktProcessingService = session.getRpcService(PacketProcessingService.class);
+ IdManagerService idManager = rpcProviderRegistry.getRpcService(IdManagerService.class);
+ OdlInterfaceRpcService interfaceService = rpcProviderRegistry.getRpcService(OdlInterfaceRpcService.class);
+ alivenessMonitor = new AlivenessMonitor(dataBroker);
+ alivenessMonitor.setPacketProcessingService(pktProcessingService);
+ alivenessMonitor.setNotificationPublishService(notificationPublishService);
+ alivenessMonitor.setIdManager(idManager);
+ alivenessMonitor.setInterfaceManager(interfaceService);
+ rpcRegistration = getRpcProviderRegistry().addRpcImplementation(AlivenessMonitorService.class, alivenessMonitor);
+ listenerRegistration = notificationService.registerNotificationListener(alivenessMonitor);
+
+ //ARP Handler
+ AlivenessProtocolHandler arpHandler = new AlivenessProtocolHandlerARP(alivenessMonitor);
+ OdlArputilService arpService = rpcProviderRegistry.getRpcService(OdlArputilService.class);
+ ((AlivenessProtocolHandlerARP) arpHandler).setArpManagerService(arpService);
+ alivenessMonitor.registerHandler(EtherTypes.Arp, arpHandler);
+
+ //LLDP Handler
+ AlivenessProtocolHandler lldpHandler = new AlivenessProtocolHandlerLLDP(alivenessMonitor);
+ alivenessMonitor.registerHandler(EtherTypes.Lldp, lldpHandler);
+
+ //TODO: Enable Interface Event Listener
+ //DelegatingInterfaceEventListener listener = new DelegatingInterfaceEventListener(alivenessMonitor);
+ //interfaceListenerRegistration = notificationService.registerNotificationListener(listener);
+ } catch (Exception e) {
+ LOG.error("Error initializing AlivenessMonitor service", e);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.alivenessmonitor.internal;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.InterfaceMonitorMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorConfigs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorProfiles;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitoridKeyMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitoringStates;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629._interface.monitor.map.InterfaceMonitorEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629._interface.monitor.map.InterfaceMonitorEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.configs.MonitoringInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.configs.MonitoringInfoKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profiles.MonitorProfile;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profiles.MonitorProfileKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitorid.key.map.MonitoridKeyEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitorid.key.map.MonitoridKeyEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitoring.states.MonitoringState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitoring.states.MonitoringStateKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.primitives.UnsignedBytes;
+
+public class AlivenessMonitorUtil {
+
+ static InstanceIdentifier<MonitoringState> getMonitorStateId(String keyId) {
+ return InstanceIdentifier.builder(MonitoringStates.class)
+ .child(MonitoringState.class, new MonitoringStateKey(keyId)).build();
+ }
+
+ static InstanceIdentifier<MonitoringInfo> getMonitoringInfoId(Long monitorId) {
+ return InstanceIdentifier.builder(MonitorConfigs.class)
+ .child(MonitoringInfo.class, new MonitoringInfoKey(monitorId)).build();
+ }
+
+ static InstanceIdentifier<MonitorProfile> getMonitorProfileId(Long profileId) {
+ return InstanceIdentifier.builder(MonitorProfiles.class)
+ .child(MonitorProfile.class, new MonitorProfileKey(profileId)).build();
+ }
+
+ static InstanceIdentifier<MonitoridKeyEntry> getMonitorMapId(Long keyId) {
+ return InstanceIdentifier.builder(MonitoridKeyMap.class)
+ .child(MonitoridKeyEntry.class, new MonitoridKeyEntryKey(keyId)).build();
+ }
+
+ static InstanceIdentifier<InterfaceMonitorEntry> getInterfaceMonitorMapId(String interfaceName) {
+ return InstanceIdentifier.builder(InterfaceMonitorMap.class)
+ .child(InterfaceMonitorEntry.class, new InterfaceMonitorEntryKey(interfaceName)).build();
+ }
+
+ public static String toStringIpAddress(byte[] ipAddress)
+ {
+ String ip = "";
+ if (ipAddress == null) {
+ return ip;
+ }
+
+ try {
+ ip = InetAddress.getByAddress(ipAddress).getHostAddress();
+ } catch(UnknownHostException e) { }
+
+ return ip;
+ }
+
+ public static String toStringMacAddress(byte[] macAddress)
+ {
+ if (macAddress == null) {
+ return "";
+ }
+
+ StringBuilder sb = new StringBuilder(18);
+
+ for (int i = 0; i < macAddress.length; i++) {
+ sb.append(UnsignedBytes.toString(macAddress[i], 16).toUpperCase());
+ sb.append(":");
+ }
+
+ sb.setLength(17);
+ return sb.toString();
+ }
+
+ public static byte[] parseIpAddress(String ipAddress) {
+ byte cur;
+
+ String[] addressPart = ipAddress.split(".");
+ int size = addressPart.length;
+
+ byte[] part = new byte[size];
+ for (int i = 0; i < size; i++) {
+ cur = UnsignedBytes.parseUnsignedByte(addressPart[i], 16);
+ part[i] = cur;
+ }
+
+ return part;
+ }
+
+ public static byte[] parseMacAddress(String macAddress) {
+ byte cur;
+
+ String[] addressPart = macAddress.split(":");
+ int size = addressPart.length;
+
+ byte[] part = new byte[size];
+ for (int i = 0; i < size; i++) {
+ cur = UnsignedBytes.parseUnsignedByte(addressPart[i], 16);
+ part[i] = cur;
+ }
+
+ return part;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.alivenessmonitor.internal;
+
+import org.opendaylight.controller.liblldp.Packet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.configs.MonitoringInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
+
+/**
+ * Protocol specific Handler interface defined by the Aliveness monitor service
+ * Handler will be registered with Alivnessmonitor service along with the protocol type
+ * it supports.
+ *
+ */
+public interface AlivenessProtocolHandler {
+
+ Class<?> getPacketClass();
+
+ String handlePacketIn(Packet protocolPacket, PacketReceived packetReceived);
+
+ void sendPacketOut(MonitoringInfo monitorInfo);
+
+ String getUniqueMonitoringKey(MonitoringInfo monitorInfo);
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.alivenessmonitor.internal;
+
+import static org.opendaylight.vpnservice.alivenessmonitor.internal.AlivenessMonitorUtil.toStringIpAddress;
+import static org.opendaylight.vpnservice.alivenessmonitor.internal.AlivenessMonitorConstants.*;
+
+import java.math.BigInteger;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.liblldp.Packet;
+import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
+import org.opendaylight.vpnservice.mdsalutil.packet.ARP;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.EtherTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.EndpointType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.endpoint.type.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.endpoint.type.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.configs.MonitoringInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpRequestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpRequestInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.interfaces.InterfaceAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.interfaces.InterfaceAddressBuilder;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+
+public class AlivenessProtocolHandlerARP extends AbstractAlivenessProtocolHandler {
+ private static final Logger LOG = LoggerFactory.getLogger(AlivenessProtocolHandlerARP.class);
+ private OdlArputilService arpService;
+
+ public AlivenessProtocolHandlerARP(ServiceProvider serviceProvider) {
+ super(serviceProvider);
+ }
+
+ void setArpManagerService(OdlArputilService arpService) {
+ this.arpService = arpService;
+ }
+
+ @Override
+ public Class<?> getPacketClass() {
+ return ARP.class;
+ }
+
+ @Override
+ public String handlePacketIn(Packet protocolPacket, PacketReceived packetReceived) {
+ ARP packet = (ARP) protocolPacket;
+ short tableId = packetReceived.getTableId().getValue();
+ int arpType = packet.getOpCode();
+
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("packet: {}, tableId {}, arpType {}", packetReceived, tableId, arpType);
+ }
+
+ if (tableId == AlivenessMonitorConstants.L3_INTERFACE_TABLE) {
+ if (arpType == ARP.REPLY) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("packet: {}, monitorKey {}", packetReceived);
+ }
+
+ BigInteger metadata = packetReceived.getMatch().getMetadata().getMetadata();
+ int portTag = MetaDataUtil.getLportFromMetadata(metadata).intValue();
+ String interfaceName = null;
+
+ try {
+ GetInterfaceFromIfIndexInput input = new GetInterfaceFromIfIndexInputBuilder().setIfIndex(portTag).build();
+ Future<RpcResult<GetInterfaceFromIfIndexOutput>> output = serviceProvider.getInterfaceManager().getInterfaceFromIfIndex(input);
+ RpcResult<GetInterfaceFromIfIndexOutput> result = output.get();
+ if(result.isSuccessful()) {
+ GetInterfaceFromIfIndexOutput ifIndexOutput = result.getResult();
+ interfaceName = ifIndexOutput.getInterfaceName();
+ } else {
+ LOG.warn("RPC call to get interface name for if index {} failed with errors {}", portTag, result.getErrors());
+ return null;
+ }
+ } catch(InterruptedException | ExecutionException e) {
+ LOG.warn("Error retrieving interface Name for tag {}", portTag, e);
+ }
+ if(!Strings.isNullOrEmpty(interfaceName)) {
+ String sourceIp = toStringIpAddress(packet.getSenderProtocolAddress());
+ String targetIp = toStringIpAddress(packet.getTargetProtocolAddress());
+ return getMonitoringKey(interfaceName, targetIp, sourceIp);
+ } else {
+ LOG.debug("No interface associated with tag {} to interpret the received ARP Reply", portTag);
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void sendPacketOut(MonitoringInfo monitorInfo) {
+ if(arpService == null) {
+ LOG.debug("ARP Service not available to send the packet");
+ return;
+ }
+ EndpointType source = monitorInfo.getSource().getEndpointType();
+ final String sourceInterface = Preconditions.checkNotNull(getInterfaceName(source),
+ "Source interface is required to send ARP Packet for monitoring");
+
+ final String srcIp = Preconditions.checkNotNull(getIpAddress(source),
+ "Source Ip address is required to send ARP Packet for monitoring");
+
+ EndpointType target = monitorInfo.getDestination().getEndpointType();
+ final String targetIp = Preconditions.checkNotNull(getIpAddress(target),
+ "Target Ip address is required to send ARP Packet for monitoring");
+
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("sendArpRequest interface {}, senderIPAddress {}, targetAddress {}", sourceInterface, srcIp, targetIp);
+ }
+
+ List<InterfaceAddress> addresses = Collections.singletonList(
+ new InterfaceAddressBuilder().setInterface(sourceInterface)
+ .setIpAddress(IpAddressBuilder.getDefaultInstance(srcIp)).build());
+ SendArpRequestInput input = new SendArpRequestInputBuilder().setInterfaceAddress(addresses)
+ .setIpaddress(IpAddressBuilder.getDefaultInstance(targetIp)).build();
+ Future<RpcResult<Void>> future = arpService.sendArpRequest(input);
+
+ final String msgFormat = String.format("Send ARP Request on interface %s to destination %s", sourceInterface, targetIp);
+ Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), new FutureCallback<RpcResult<Void>>() {
+ @Override
+ public void onFailure(Throwable error) {
+ LOG.error("Error - {}", msgFormat, error);
+ }
+
+ @Override
+ public void onSuccess(RpcResult<Void> result) {
+ if(!result.isSuccessful()) {
+ LOG.warn("Rpc call to {} failed {}", msgFormat, getErrorText(result.getErrors()));
+ } else {
+ LOG.debug("Successful RPC Result - {}", msgFormat);
+ }
+ }
+ });
+ }
+
+ private String getErrorText(Collection<RpcError> errors) {
+ StringBuilder errorText = new StringBuilder();
+ for(RpcError error : errors) {
+ errorText.append(",").append(error.getErrorType()).append("-")
+ .append(error.getMessage());
+ }
+ return errorText.toString();
+ }
+
+ @Override
+ public String getUniqueMonitoringKey(MonitoringInfo monitorInfo) {
+ String interfaceName = getInterfaceName(monitorInfo.getSource().getEndpointType());
+ String sourceIp = getIpAddress(monitorInfo.getSource().getEndpointType());
+ String targetIp = getIpAddress(monitorInfo.getDestination().getEndpointType());
+ return getMonitoringKey(interfaceName, sourceIp, targetIp);
+ }
+
+ private String getMonitoringKey(String interfaceName, String sourceIp, String targetIp) {
+ return new StringBuilder().append(interfaceName).append(SEPERATOR).append(sourceIp)
+ .append(SEPERATOR).append(targetIp).append(SEPERATOR).append(EtherTypes.Arp).toString();
+ }
+
+ private String getIpAddress(EndpointType source) {
+ String ipAddress = null;
+ if( source instanceof IpAddress) {
+ ipAddress = ((IpAddress) source).getIpAddress().getIpv4Address().getValue();
+ } else if (source instanceof Interface) {
+ ipAddress = ((Interface)source).getInterfaceIp().getIpv4Address().getValue();
+ }
+ return ipAddress;
+ }
+
+ private String getInterfaceName(EndpointType endpoint) {
+ String interfaceName = null;
+ if(endpoint instanceof Interface) {
+ interfaceName = ((Interface)endpoint).getInterfaceName();
+ }
+ return interfaceName;
+ }
+
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.alivenessmonitor.internal;
+
+import java.math.BigInteger;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.Future;
+
+import org.apache.commons.lang3.StringUtils;
+import org.opendaylight.controller.liblldp.EtherTypes;
+import org.opendaylight.controller.liblldp.LLDP;
+import org.opendaylight.controller.liblldp.LLDPTLV;
+import org.opendaylight.controller.liblldp.LLDPTLV.TLVType;
+import org.opendaylight.controller.liblldp.Packet;
+import org.opendaylight.controller.liblldp.PacketException;
+import org.opendaylight.vpnservice.interfacemgr.globals.IfmConstants;
+import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.ActionType;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
+import org.opendaylight.vpnservice.mdsalutil.packet.Ethernet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.EndpointType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.endpoint.type.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.configs.MonitoringInfo;
+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.InterfaceType;
+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.GetDpidFromInterfaceInput;
+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.GetInterfaceFromIfIndexInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexOutput;
+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.GetPortFromInterfaceInput;
+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 com.google.common.base.Strings;
+
+public class AlivenessProtocolHandlerLLDP extends AbstractAlivenessProtocolHandler {
+ private static final Logger LOG = LoggerFactory.getLogger(AlivenessProtocolHandlerLLDP.class);
+ private AtomicInteger packetId = new AtomicInteger(0);
+
+ public AlivenessProtocolHandlerLLDP(ServiceProvider serviceProvider) {
+ super(serviceProvider);
+ }
+
+ @Override
+ public Class<?> getPacketClass() {
+ return LLDP.class;
+ }
+
+ @Override
+ public String handlePacketIn(Packet protocolPacket, PacketReceived packetReceived) {
+ String sSourceDpnId = null;
+ String sPortNumber = null;
+ int nServiceId = -1;
+ int packetId = 0;
+
+ String sTmp = null;
+
+ byte lldpTlvTypeCur;
+
+ LLDP lldpPacket = (LLDP)protocolPacket;
+
+ LLDPTLV lldpTlvCur = lldpPacket.getSystemNameId();
+ if (lldpTlvCur != null) {
+ sSourceDpnId = new String(lldpTlvCur.getValue(), Charset.defaultCharset());
+ }
+
+ lldpTlvCur = lldpPacket.getPortId();
+ if (lldpTlvCur != null) {
+ sPortNumber = new String(lldpTlvCur.getValue(), Charset.defaultCharset());
+ }
+
+ for (LLDPTLV lldpTlv : lldpPacket.getOptionalTLVList()) {
+ lldpTlvTypeCur = lldpTlv.getType();
+
+ if (lldpTlvTypeCur == LLDPTLV.TLVType.SystemName.getValue()) {
+ sSourceDpnId = new String(lldpTlvCur.getValue(), Charset.defaultCharset());
+ }
+ }
+
+ for (LLDPTLV lldpTlv : lldpPacket.getCustomTlvList()) {
+ lldpTlvTypeCur = lldpTlv.getType();
+
+ if (lldpTlvTypeCur == LLDPTLV.TLVType.Custom.getValue()) {
+ sTmp = new String(lldpTlv.getValue());
+ nServiceId = 0;
+ }
+ }
+
+ String interfaceName = null;
+
+ //TODO: Check if the below fields are required
+ if (!Strings.isNullOrEmpty(sTmp) && sTmp.contains("#")) {
+ String[] asTmp = sTmp.split("#");
+ interfaceName = asTmp[0];
+ packetId = Integer.parseInt(asTmp[1]);
+ LOG.debug("Custom LLDP Value on received packet: " + sTmp);
+ }
+
+ if(!Strings.isNullOrEmpty(interfaceName)) {
+ String monitorKey = new StringBuilder().append(interfaceName).append(EtherTypes.LLDP).toString();
+ return monitorKey;
+ } else {
+ LOG.debug("No associated interface found to handle received LLDP Packet");
+ }
+ return null;
+ }
+
+ @Override
+ public void sendPacketOut(MonitoringInfo monitorInfo) {
+ String sourceInterface;
+
+ EndpointType source = monitorInfo.getSource().getEndpointType();
+ if( source instanceof Interface) {
+ Interface intf = (Interface)source;
+ sourceInterface = intf.getInterfaceName();
+ } else {
+ LOG.warn("Invalid source endpoint. Could not retrieve source interface to send LLDP Packet");
+ return;
+ }
+
+ //Get Mac Address for the source interface
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState = getInterfaceFromOperDS(sourceInterface);
+ byte[] sourceMac = getMacAddress(interfaceState, sourceInterface);
+ if(sourceMac == null) {
+ LOG.error("Could not read mac address for the source interface {} from the Inventory. "
+ + "LLDP packet cannot be send.", sourceInterface);
+ return;
+ }
+
+ OdlInterfaceRpcService interfaceService = serviceProvider.getInterfaceManager();
+
+ long nodeId = -1, portNum = -1;
+ try {
+ String lowerLayerIf = interfaceState.getLowerLayerIf().get(0);
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
+ nodeId = Long.valueOf(getDpnFromNodeConnectorId(nodeConnectorId));
+ portNum = Long.valueOf(getPortNoFromNodeConnectorId(nodeConnectorId));
+ }catch(Exception e) {
+ LOG.error("Failed to retrieve node id and port number ", e);
+ return;
+ }
+
+ Ethernet ethenetLLDPPacket = makeLLDPPacket(Long.toString(nodeId), portNum, 0, sourceMac, sourceInterface);
+
+ try {
+ List<ActionInfo> actions = getInterfaceActions(interfaceState, portNum);
+ if(actions.isEmpty()) {
+ LOG.error("No interface actions to send packet out over interface {}", sourceInterface);
+ return;
+ }
+ TransmitPacketInput transmitPacketInput = MDSALUtil.getPacketOut(actions,
+ ethenetLLDPPacket.serialize(), nodeId, MDSALUtil.getNodeConnRef(BigInteger.valueOf(nodeId), "0xfffffffd"));
+ serviceProvider.getPacketProcessingService().transmitPacket(transmitPacketInput);
+ } catch (Exception e) {
+ LOG.error("Error while sending LLDP Packet", e);
+ }
+ }
+
+ public static String getDpnFromNodeConnectorId(NodeConnectorId portId) {
+ /*
+ * NodeConnectorId is of form 'openflow:dpnid:portnum'
+ */
+ String[] split = portId.getValue().split(IfmConstants.OF_URI_SEPARATOR);
+ return split[1];
+ }
+
+ public static String getPortNoFromNodeConnectorId(NodeConnectorId portId) {
+ /*
+ * NodeConnectorId is of form 'openflow:dpnid:portnum'
+ */
+ String[] split = portId.getValue().split(IfmConstants.OF_URI_SEPARATOR);
+ return split[2];
+ }
+ private List<ActionInfo> getInterfaceActions(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState,long portNum) throws InterruptedException, ExecutionException {
+ Class<? extends InterfaceType> intfType;
+ if(interfaceState != null) {
+ intfType = interfaceState.getType();
+ } else {
+ LOG.error("Could not retrieve port type for interface {} to construct actions", interfaceState.getName());
+ return Collections.emptyList();
+ }
+
+ List<ActionInfo> actionInfos = new ArrayList<ActionInfo>();
+ // Set the LLDP service Id which is 0
+ if(Tunnel.class.equals(intfType)) {
+ actionInfos.add(new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
+ BigInteger.valueOf(0)}));
+ }
+ actionInfos.add(new ActionInfo(ActionType.output, new String[] { Long.toString(portNum) }));
+ return actionInfos;
+ }
+
+ private static LLDPTLV buildLLDTLV(LLDPTLV.TLVType tlvType,byte[] abyTLV) {
+ return new LLDPTLV().setType(tlvType.getValue()).setLength((short) abyTLV.length).setValue(abyTLV);
+ }
+
+ private int getPacketId() {
+ int id = packetId.incrementAndGet();
+ if(id > 16000) {
+ LOG.debug("Resetting the LLDP Packet Id counter");
+ packetId.set(0);
+ }
+
+ return id;
+ }
+
+ public Ethernet makeLLDPPacket(String nodeId,
+ long portNum, int serviceId, byte[] srcMac, String sourceInterface) {
+
+ // Create LLDP TTL TLV
+ LLDPTLV lldpTlvTTL = buildLLDTLV(LLDPTLV.TLVType.TTL, new byte[] { (byte) 0, (byte) 120 });
+
+ LLDPTLV lldpTlvChassisId = buildLLDTLV(LLDPTLV.TLVType.ChassisID, LLDPTLV.createChassisIDTLVValue(colonize(StringUtils
+ .leftPad(Long.toHexString(MDSALUtil.getDpnIdFromNodeName(nodeId).longValue()), 16,
+ "0"))));
+ LLDPTLV lldpTlvSystemName = buildLLDTLV(TLVType.SystemName, LLDPTLV.createSystemNameTLVValue(nodeId));
+
+ LLDPTLV lldpTlvPortId = buildLLDTLV(TLVType.PortID, LLDPTLV.createPortIDTLVValue(
+ Long.toHexString(portNum)));
+
+ String customValue = sourceInterface + "#" + getPacketId();
+
+ LOG.debug("Sending LLDP packet, custome value " + customValue);
+
+ LLDPTLV lldpTlvCustom = buildLLDTLV(TLVType.Custom, customValue.getBytes());
+
+ List<LLDPTLV> lstLLDPTLVCustom = new ArrayList<>();
+ lstLLDPTLVCustom.add(lldpTlvCustom);
+
+ LLDP lldpDiscoveryPacket = new LLDP();
+ lldpDiscoveryPacket.setChassisId(lldpTlvChassisId)
+ .setPortId(lldpTlvPortId)
+ .setTtl(lldpTlvTTL)
+ .setSystemNameId(lldpTlvSystemName)
+ .setOptionalTLVList(lstLLDPTLVCustom);
+
+ byte[] destMac = LLDP.LLDPMulticastMac;
+
+ Ethernet ethernetPacket = new Ethernet();
+ ethernetPacket.setSourceMACAddress(srcMac)
+ .setDestinationMACAddress(destMac)
+ .setEtherType(EtherTypes.LLDP.shortValue())
+ .setPayload(lldpDiscoveryPacket);
+
+ return ethernetPacket;
+ }
+
+ private String colonize(String orig) {
+ return orig.replaceAll("(?<=..)(..)", ":$1");
+ }
+
+ @Override
+ public String getUniqueMonitoringKey(MonitoringInfo monitorInfo) {
+ String interfaceName = getInterfaceName(monitorInfo.getSource().getEndpointType());
+ return new StringBuilder().append(interfaceName).append(EtherTypes.LLDP).toString();
+ }
+
+ private String getInterfaceName(EndpointType endpoint) {
+ String interfaceName = null;
+ if(endpoint instanceof Interface) {
+ interfaceName = ((Interface)endpoint).getInterfaceName();
+ }
+ return interfaceName;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.alivenessmonitor.internal;
+
+interface InterfaceStateListener {
+
+ void onInterfaceStateUp(String interfaceName);
+
+ void onInterfaceStateDown(String interfaceName);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.alivenessmonitor.internal;
+
+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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.primitives.UnsignedBytes;
+
+class InventoryReader {
+ private Logger LOG = LoggerFactory.getLogger(InventoryReader.class);
+ private DataBroker dataService;
+
+ public InventoryReader(DataBroker dataService) {
+ this.dataService = dataService;
+ }
+
+ public String getMacAddress(InstanceIdentifier<NodeConnector> nodeConnectorId) {
+ //TODO: Use mdsal apis to read
+ Optional<NodeConnector> optNc = read(LogicalDatastoreType.OPERATIONAL, nodeConnectorId);
+ if(optNc.isPresent()) {
+ NodeConnector nc = optNc.get();
+ FlowCapableNodeConnector fcnc = nc.getAugmentation(FlowCapableNodeConnector.class);
+ MacAddress macAddress = fcnc.getHardwareAddress();
+ return macAddress.getValue();
+ }
+ return null;
+ }
+
+ private <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path) {
+
+ ReadOnlyTransaction tx = dataService.newReadOnlyTransaction();
+
+ Optional<T> result = Optional.absent();
+ try {
+ result = tx.read(datastoreType, path).get();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ tx.close();
+
+ return result;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.alivenessmonitor.internal;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
+
+/**
+ * Provides access methods to retrieve the reference to the dependent service
+ *
+ */
+interface ServiceProvider {
+
+ DataBroker getDataBroker();
+
+ PacketProcessingService getPacketProcessingService();
+
+ OdlInterfaceRpcService getInterfaceManager();
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.alivenessmonitor.internal;
+
+/**
+ * Exception indicating the config provided is not supported currently
+ *
+ *
+ */
+public class UnsupportedConfigException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public UnsupportedConfigException(String message){
+ super(message);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.alivenessmonitor.impl.rev150706;
+
+import org.opendaylight.vpnservice.alivenessmonitor.internal.AlivenessMonitorProvider;
+
+public class AlivenessMonitorModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.alivenessmonitor.impl.rev150706.AbstractAlivenessMonitorModule {
+ public AlivenessMonitorModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public AlivenessMonitorModule(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.alivenessmonitor.impl.rev150706.AlivenessMonitorModule 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() {
+ AlivenessMonitorProvider provider = new AlivenessMonitorProvider(getRpcRegistryDependency());
+ provider.setNotificationPublishService(getNotificationPublishServiceDependency());
+ provider.setNotificationService(getNotificationServiceDependency());
+ getBrokerDependency().registerProvider(provider);
+ return provider;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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
+ */
+
+/*
+* Generated file
+*
+* Generated from: yang module name: alivenessmonitor-impl yang module local name: alivenessmonitor-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Mon Jul 06 11:45:33 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.alivenessmonitor.impl.rev150706;
+public class AlivenessMonitorModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.alivenessmonitor.impl.rev150706.AbstractAlivenessMonitorModuleFactory {
+
+}
--- /dev/null
+module alivenessmonitor-impl {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:alivenessmonitor:impl";
+ prefix "alivenessmonitor-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 odl-interface {prefix odlif; revision-date 2015-03-31;}
+ //import aliveness-monitor { prefix aliveness-mon; revision-date 2015-06-29; }
+
+ description
+ "Service definition for aliveness monitor module";
+
+ revision "2015-07-06" {
+ description
+ "Initial revision";
+ }
+
+ identity alivenessmonitor-impl {
+ base config:module-type;
+ config:java-name-prefix AlivenessMonitor;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case alivenessmonitor-impl {
+ when "/config:modules/config:module/config:type = 'alivenessmonitor-impl'";
+ container broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-broker-osgi-registry;
+ }
+ }
+ }
+ container rpc-registry {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-rpc-registry;
+ }
+ }
+ }
+ container notification-publish-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding-impl:binding-new-notification-publish-service;
+ }
+ }
+ }
+ container notification-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding-impl:binding-new-notification-service;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.controller.alivenessmonitor.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.times;
+import static org.mockito.Matchers.argThat;
+
+import java.util.Arrays;
+
+import org.hamcrest.CoreMatchers;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.vpnservice.alivenessmonitor.internal.AlivenessMonitor;
+import org.opendaylight.vpnservice.alivenessmonitor.internal.AlivenessProtocolHandler;
+import org.opendaylight.vpnservice.alivenessmonitor.internal.AlivenessProtocolHandlerARP;
+import org.opendaylight.vpnservice.alivenessmonitor.internal.AlivenessProtocolHandlerLLDP;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.EtherTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorPauseInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorPauseInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorProfileCreateInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorProfileCreateInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorProfileCreateOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorProfileDeleteInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorProfileDeleteInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorStartInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorStartInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorStartOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorStopInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorStopInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorUnpauseInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorUnpauseInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitoringMode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629._interface.monitor.map.InterfaceMonitorEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629._interface.monitor.map.InterfaceMonitorEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.endpoint.type.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.endpoint.type.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.configs.MonitoringInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.configs.MonitoringInfoBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.params.DestinationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.params.SourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profile.create.input.ProfileBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profiles.MonitorProfile;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profiles.MonitorProfileBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.start.input.ConfigBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitorid.key.map.MonitoridKeyEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitorid.key.map.MonitoridKeyEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitoring.states.MonitoringState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitoring.states.MonitoringStateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+
+public class AlivenessMonitorTest {
+
+ @Mock private DataBroker dataBroker;
+ @Mock private IdManagerService idManager;
+ @Mock private PacketProcessingService packetProcessingService;
+ @Mock private NotificationPublishService notificationPublishService;
+ private AlivenessMonitor alivenessMonitor;
+ private AlivenessProtocolHandler arpHandler;
+ private AlivenessProtocolHandler lldpHandler;
+ private long mockId;
+ @Mock private ReadOnlyTransaction readTx;
+ @Mock private WriteTransaction writeTx;
+ @Mock private ReadWriteTransaction readWriteTx;
+ @Captor ArgumentCaptor<MonitoringState> stateCaptor;
+
+ private <T extends DataObject> Matcher<InstanceIdentifier<T>> isType(final Class<T> klass) {
+ return new TypeSafeMatcher<InstanceIdentifier<T>>() {
+ @Override
+ public void describeTo(Description desc) {
+ desc.appendText("Instance Identifier should have Target Type " + klass);
+ }
+
+ @Override
+ protected boolean matchesSafely(InstanceIdentifier<T> id) {
+ return id.getTargetType().equals(klass);
+ }
+ };
+ }
+
+ private Matcher<RpcError> hasErrorType(final ErrorType errorType) {
+ return new TypeSafeMatcher<RpcError>() {
+ @Override
+ public void describeTo(Description desc) {
+ desc.appendText("Error type do not match " + errorType);
+ }
+
+ @Override
+ protected boolean matchesSafely(RpcError error) {
+ return error.getErrorType().equals(errorType);
+ }
+ };
+ }
+
+ @SuppressWarnings("unchecked")
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ alivenessMonitor = new AlivenessMonitor(dataBroker);
+ when(idManager.createIdPool(any(CreateIdPoolInput.class)))
+ .thenReturn(Futures.immediateFuture(RpcResultBuilder.<Void>success().build()));
+ alivenessMonitor.setIdManager(idManager);
+ alivenessMonitor.setNotificationPublishService(notificationPublishService);
+ alivenessMonitor.setPacketProcessingService(packetProcessingService);
+
+ arpHandler = new AlivenessProtocolHandlerARP(alivenessMonitor);
+ alivenessMonitor.registerHandler(EtherTypes.Arp, arpHandler);
+
+ lldpHandler = new AlivenessProtocolHandlerLLDP(alivenessMonitor);
+ alivenessMonitor.registerHandler(EtherTypes.Lldp, lldpHandler);
+ mockId = 1L;
+ when(idManager.allocateId(any(AllocateIdInput.class)))
+ .thenReturn(Futures.immediateFuture(RpcResultBuilder.success(new AllocateIdOutputBuilder().setIdValue(mockId++).build()).build()));
+ when(idManager.releaseId(any(ReleaseIdInput.class))).thenReturn(Futures.immediateFuture(RpcResultBuilder.<Void>success().build()));
+ doReturn(readTx).when(dataBroker).newReadOnlyTransaction();
+ doReturn(writeTx).when(dataBroker).newWriteOnlyTransaction();
+ doReturn(readWriteTx).when(dataBroker).newReadWriteTransaction();
+ doNothing().when(writeTx).put(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class), any(DataObject.class));
+ doReturn(Futures.immediateCheckedFuture(null)).when(writeTx).submit();
+ doReturn(Futures.immediateCheckedFuture(null)).when(readWriteTx).submit();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ alivenessMonitor.close();
+ }
+
+ @Test
+ public void testMonitorProfileCreate() throws Throwable {
+ MonitorProfileCreateInput input = new MonitorProfileCreateInputBuilder().setProfile(new ProfileBuilder().setFailureThreshold(10L)
+ .setMonitorInterval(10000L).setMonitorWindow(10L).setProtocolType(EtherTypes.Arp).build()).build();
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(readWriteTx).read(eq(LogicalDatastoreType.OPERATIONAL), argThat(isType(MonitorProfile.class)));
+ doReturn(Futures.immediateCheckedFuture(null)).when(readWriteTx).submit();
+ RpcResult<MonitorProfileCreateOutput> output = alivenessMonitor.monitorProfileCreate(input).get();
+ assertTrue("Monitor Profile Create result", output.isSuccessful());
+ assertNotNull("Monitor Profile Output", output.getResult().getProfileId());
+ }
+
+ @Test
+ public void testMonitorProfileCreateAlreadyExist() throws Throwable {
+ MonitorProfileCreateInput input = new MonitorProfileCreateInputBuilder().setProfile(new ProfileBuilder().setFailureThreshold(10L)
+ .setMonitorInterval(10000L).setMonitorWindow(10L).setProtocolType(EtherTypes.Arp).build()).build();
+ @SuppressWarnings("unchecked")
+ Optional<MonitorProfile> optionalProfile = (Optional<MonitorProfile>)mock(Optional.class);
+ CheckedFuture<Optional<MonitorProfile>, ReadFailedException> proFuture = Futures.immediateCheckedFuture(optionalProfile);
+ doReturn(true).when(optionalProfile).isPresent();
+ doReturn(proFuture).when(readWriteTx).read(eq(LogicalDatastoreType.OPERATIONAL), argThat(isType(MonitorProfile.class)));
+ RpcResult<MonitorProfileCreateOutput> output = alivenessMonitor.monitorProfileCreate(input).get();
+ assertTrue("Monitor Profile Create result", output.isSuccessful());
+ assertThat(output.getErrors(), CoreMatchers.hasItem(hasErrorType(ErrorType.PROTOCOL)));
+ }
+
+ @Test
+ public void testMonitorStart() throws Throwable {
+ Long profileId = createProfile();
+ MonitorStartInput input = new MonitorStartInputBuilder().setConfig(new ConfigBuilder()
+ .setDestination(new DestinationBuilder().setEndpointType(getInterface("10.0.0.1")).build())
+ .setSource(new SourceBuilder().setEndpointType(getInterface("testInterface", "10.1.1.1")).build())
+ .setMode(MonitoringMode.OneOne)
+ .setProfileId(profileId).build()).build();
+ @SuppressWarnings("unchecked")
+ Optional<MonitorProfile> optionalProfile = (Optional<MonitorProfile>)mock(Optional.class);
+ CheckedFuture<Optional<MonitorProfile>, ReadFailedException> proFuture = Futures.immediateCheckedFuture(optionalProfile);
+ when(readTx.read(eq(LogicalDatastoreType.OPERATIONAL), argThat(isType(MonitorProfile.class)))).thenReturn(proFuture);
+ doReturn(true).when(optionalProfile).isPresent();
+ doReturn(getTestMonitorProfile()).when(optionalProfile).get();
+ CheckedFuture<Optional<MonitoringInfo>, ReadFailedException> outFuture = Futures.immediateCheckedFuture(Optional.<MonitoringInfo>absent());
+ when(readTx.read(eq(LogicalDatastoreType.OPERATIONAL), argThat(isType(MonitoringInfo.class)))).thenReturn(outFuture);
+ RpcResult<MonitorStartOutput> output = alivenessMonitor.monitorStart(input).get();
+ verify(idManager, times(2)).allocateId(any(AllocateIdInput.class));
+ assertTrue("Monitor start output result", output.isSuccessful());
+ assertNotNull("Monitor start output", output.getResult().getMonitorId());
+ }
+
+ @Test
+ public void testMonitorPause() throws Throwable {
+ MonitorPauseInput input = new MonitorPauseInputBuilder().setMonitorId(2L).build();
+ Optional<MonitoringState> optState = Optional.of(new MonitoringStateBuilder().setStatus(MonitorStatus.Started).build());
+ when(readWriteTx.read(eq(LogicalDatastoreType.OPERATIONAL), argThat(isType(MonitoringState.class)))).
+ thenReturn(Futures.<Optional<MonitoringState>, ReadFailedException>immediateCheckedFuture(optState));
+ Optional<MonitoridKeyEntry> optMap = Optional.of(new MonitoridKeyEntryBuilder().setMonitorId(2L).setMonitorKey("Test monitor Key").build());
+ when(readTx.read(eq(LogicalDatastoreType.OPERATIONAL), argThat(isType(MonitoridKeyEntry.class)))).
+ thenReturn(Futures.<Optional<MonitoridKeyEntry>, ReadFailedException>immediateCheckedFuture(optMap));
+ alivenessMonitor.monitorPause(input).get();
+ verify(readWriteTx).merge(eq(LogicalDatastoreType.OPERATIONAL), argThat(isType(MonitoringState.class)), stateCaptor.capture());
+ assertEquals(MonitorStatus.Paused, stateCaptor.getValue().getStatus());
+ }
+
+ @Test
+ public void testMonitorUnpause() throws Throwable {
+ MonitorUnpauseInput input = new MonitorUnpauseInputBuilder().setMonitorId(2L).build();
+ Optional<MonitoringState> optState = Optional.of(new MonitoringStateBuilder().setStatus(MonitorStatus.Paused).build());
+ when(readWriteTx.read(eq(LogicalDatastoreType.OPERATIONAL), argThat(isType(MonitoringState.class)))).
+ thenReturn(Futures.<Optional<MonitoringState>, ReadFailedException>immediateCheckedFuture(optState));
+ Optional<MonitoringInfo> optInfo = Optional.of(new MonitoringInfoBuilder().setId(2L).setProfileId(1L).build());
+ when(readTx.read(eq(LogicalDatastoreType.OPERATIONAL), argThat(isType(MonitoringInfo.class)))).
+ thenReturn(Futures.<Optional<MonitoringInfo>, ReadFailedException>immediateCheckedFuture(optInfo));
+ Optional<MonitorProfile> optProfile = Optional.of(getTestMonitorProfile());
+ when(readTx.read(eq(LogicalDatastoreType.OPERATIONAL), argThat(isType(MonitorProfile.class)))).
+ thenReturn(Futures.<Optional<MonitorProfile>, ReadFailedException>immediateCheckedFuture(optProfile));
+ Optional<MonitoridKeyEntry> optMap = Optional.of(new MonitoridKeyEntryBuilder().setMonitorId(2L).setMonitorKey("Test monitor Key").build());
+ when(readTx.read(eq(LogicalDatastoreType.OPERATIONAL), argThat(isType(MonitoridKeyEntry.class)))).
+ thenReturn(Futures.<Optional<MonitoridKeyEntry>, ReadFailedException>immediateCheckedFuture(optMap));
+ RpcResult<Void> result = alivenessMonitor.monitorUnpause(input).get();
+ verify(readWriteTx).merge(eq(LogicalDatastoreType.OPERATIONAL), argThat(isType(MonitoringState.class)), stateCaptor.capture());
+ assertEquals(MonitorStatus.Started, stateCaptor.getValue().getStatus());
+ assertTrue("Monitor unpause rpc result", result.isSuccessful());
+ }
+
+ @Test
+ public void testMonitorStop() throws Throwable {
+ MonitorStopInput input = new MonitorStopInputBuilder().setMonitorId(2L).build();
+ Optional<MonitoringInfo> optInfo = Optional.of(
+ new MonitoringInfoBuilder().setSource(new SourceBuilder().setEndpointType(getInterface("testInterface", "10.1.1.1")).build()).build());
+ CheckedFuture<Optional<MonitoringInfo>, ReadFailedException> outFuture = Futures.immediateCheckedFuture(optInfo);
+ when(readTx.read(eq(LogicalDatastoreType.OPERATIONAL), argThat(isType(MonitoringInfo.class)))).thenReturn(outFuture);
+ Optional<MonitoridKeyEntry> optMap = Optional.of(new MonitoridKeyEntryBuilder().setMonitorId(2L).setMonitorKey("Test monitor Key").build());
+ when(readTx.read(eq(LogicalDatastoreType.OPERATIONAL), argThat(isType(MonitoridKeyEntry.class)))).
+ thenReturn(Futures.<Optional<MonitoridKeyEntry>, ReadFailedException>immediateCheckedFuture(optMap));
+ Optional<MonitorProfile> optProfile = Optional.of(getTestMonitorProfile());
+ when(readTx.read(eq(LogicalDatastoreType.OPERATIONAL), argThat(isType(MonitorProfile.class)))).
+ thenReturn(Futures.<Optional<MonitorProfile>, ReadFailedException>immediateCheckedFuture(optProfile));
+ Optional<InterfaceMonitorEntry> optEntry = Optional.of(getInterfaceMonitorEntry());
+ when(readWriteTx.read(eq(LogicalDatastoreType.OPERATIONAL), argThat(isType(InterfaceMonitorEntry.class)))).
+ thenReturn(Futures.<Optional<InterfaceMonitorEntry>, ReadFailedException>immediateCheckedFuture(optEntry));
+ RpcResult<Void> result = alivenessMonitor.monitorStop(input).get();
+ verify(idManager).releaseId(any(ReleaseIdInput.class));
+ verify(writeTx, times(2)).delete(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class));
+ assertTrue("Monitor stop rpc result", result.isSuccessful());
+ }
+
+ @Test
+ public void testMonitorProfileDelete() throws Throwable {
+ MonitorProfileDeleteInput input = new MonitorProfileDeleteInputBuilder().setProfileId(1L).build();
+ Optional<MonitorProfile> optProfile = Optional.of(getTestMonitorProfile());
+ when(readWriteTx.read(eq(LogicalDatastoreType.OPERATIONAL), argThat(isType(MonitorProfile.class)))).
+ thenReturn(Futures.<Optional<MonitorProfile>, ReadFailedException>immediateCheckedFuture(optProfile));
+ RpcResult<Void> result = alivenessMonitor.monitorProfileDelete(input).get();
+ verify(idManager).releaseId(any(ReleaseIdInput.class));
+ verify(readWriteTx).delete(eq(LogicalDatastoreType.OPERATIONAL), Matchers.<InstanceIdentifier<MonitorProfile>>any());
+ assertTrue("Monitor profile delete result", result.isSuccessful());
+ }
+
+ @SuppressWarnings("unchecked")
+ private long createProfile() throws Throwable{
+ MonitorProfileCreateInput input = new MonitorProfileCreateInputBuilder().setProfile(new ProfileBuilder().setFailureThreshold(10L)
+ .setMonitorInterval(10000L).setMonitorWindow(10L).setProtocolType(EtherTypes.Arp).build()).build();
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(readWriteTx).read(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class));
+ doReturn(Futures.immediateCheckedFuture(null)).when(readWriteTx).submit();
+ RpcResult<MonitorProfileCreateOutput> output = alivenessMonitor.monitorProfileCreate(input).get();
+ return output.getResult().getProfileId();
+ }
+
+ private MonitorProfile getTestMonitorProfile() {
+ return new MonitorProfileBuilder().setFailureThreshold(10L).setMonitorInterval(10000L)
+ .setMonitorWindow(10L).setProtocolType(EtherTypes.Arp).build();
+ }
+
+ private InterfaceMonitorEntry getInterfaceMonitorEntry() {
+ return new InterfaceMonitorEntryBuilder().setInterfaceName("test-interface").setMonitorIds(Arrays.asList(1L, 2L)).build();
+ }
+
+ private Interface getInterface(String ipAddress) {
+ return new InterfaceBuilder().setInterfaceIp(IpAddressBuilder.getDefaultInstance(ipAddress)).build();
+ }
+
+ private Interface getInterface(String interfaceName, String ipAddress) {
+ return new InterfaceBuilder().setInterfaceIp(IpAddressBuilder.getDefaultInstance(ipAddress)).setInterfaceName(interfaceName).build();
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>alivenessmonitor-aggregator</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <name>alivenessmonitor</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>alivenessmonitor-api</module>
+ <module>alivenessmonitor-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>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>arputil-api</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.model</groupId>
+ <artifactId>model-flow-base</artifactId>
+ <version>${openflowplugin.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.model</groupId>
+ <artifactId>model-flow-service</artifactId>
+ <version>${openflowplugin.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</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>
+ </dependencies>
+</project>
--- /dev/null
+module odl-arputil {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:arputil";
+ prefix "odl-arputil";
+
+ import ietf-interfaces {
+ prefix if;
+ }
+
+ import ietf-inet-types {
+ prefix inet;
+ }
+
+ import ietf-yang-types {
+ prefix yang;
+ }
+
+ import opendaylight-inventory {
+ prefix inv; revision-date 2013-08-19;
+ }
+
+ import config {
+ prefix config; revision-date 2013-04-05;
+ }
+
+ revision "2015-11-26" {
+ description "Arp Util module";
+ }
+
+
+ grouping interfaces {
+ list interface-address {
+ key interface;
+ leaf interface {
+ type leafref {
+ path "/if:interfaces/if:interface/if:name";
+ }
+ }
+ leaf ip-address {
+ type inet:ip-address;
+ }
+ }
+ }
+
+
+ rpc get-mac {
+ input {
+ leaf ipaddress {
+ type inet:ip-address;
+ }
+ uses interfaces;
+ }
+ output {
+ leaf macaddress {
+ type yang:phys-address;
+ }
+ }
+ }
+
+ rpc send-arp-request {
+ input {
+ leaf ipaddress {
+ type inet:ip-address;
+ }
+ uses interfaces;
+ }
+ }
+
+ rpc send-arp-response {
+ input {
+ leaf ipaddress {
+ type inet:ip-address;
+ }
+ leaf macaddress {
+ type yang:phys-address;
+ }
+ leaf interface {
+ type leafref {
+ path "/if:interfaces/if:interface/if:name";
+ }
+ }
+ leaf src-ip-address {
+ type inet:ip-address;
+ }
+ }
+ }
+
+
+ notification mac-changed {
+ leaf ipaddress {
+ type inet:ip-address;
+ }
+ leaf macaddress {
+ type yang:phys-address;
+ }
+ leaf interface {
+ type leafref {
+ path "/if:interfaces/if:interface/if:name";
+ }
+ }
+ }
+
+ notification arp-request-received {
+ leaf dst-ipaddress {
+ type inet:ip-address;
+ }
+ leaf src-ipaddress {
+ type inet:ip-address;
+ }
+ leaf src-mac {
+ type yang:phys-address;
+ }
+ leaf of-table-id {
+ type uint32;
+ }
+ leaf interface {
+ type leafref {
+ path "/if:interfaces/if:interface/if:name";
+ }
+ }
+ }
+
+ notification arp-response-received {
+ leaf ipaddress {
+ type inet:ip-address;
+ }
+ leaf macaddress {
+ type yang:phys-address;
+ }
+ leaf of-table-id {
+ type uint32;
+ }
+ leaf interface {
+ type leafref {
+ path "/if:interfaces/if:interface/if:name";
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>arputil-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+ <properties>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>interfacemgr-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mdsalutil-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>yang-ext</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>liblldp</artifactId>
+ <version>${liblldp.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-inet-types</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>arputil-api</artifactId>
+ <version>${project.version}</version>
+ </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.openflowplugin.model</groupId>
+ <artifactId>model-flow-base</artifactId>
+ <version>${openflowplugin.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.model</groupId>
+ <artifactId>model-flow-service</artifactId>
+ <version>${openflowplugin.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <version>${mdsal.version}</version>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+ </dependencies>
+
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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:arputil:impl?module=arputil-impl&revision=2015-11-26</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>
+ </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:arputil:impl">prefix:arputil-impl</type>
+ <name>arputil-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>
+ <rpc-registry>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+ <name>binding-rpc-broker</name>
+ </rpc-registry>
+ <mdsalutil>
+ <type xmlns:mdsalutil="urn:opendaylight:params:xml:ns:yang:mdsalutil:api">mdsalutil:odl-mdsalutil</type>
+ <name>mdsalutil-service</name>
+ </mdsalutil>
+ <notification-publish-service>
+ <type xmlns:bindingimpl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">bindingimpl:binding-new-notification-publish-service</type>
+ <name>binding-notification-publish-adapter</name>
+ </notification-publish-service>
+ <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>
+ </data>
+ </configuration>
+</snapshot>
--- /dev/null
+/*
+ * Copyright (c) 2015 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.arputil.internal;
+
+import org.opendaylight.controller.liblldp.EtherTypes;
+import org.opendaylight.controller.liblldp.PacketException;
+import org.opendaylight.vpnservice.mdsalutil.packet.ARP;
+import org.opendaylight.vpnservice.mdsalutil.packet.Ethernet;
+
+public class ArpPacketUtil {
+
+ public static byte[] EthernetDestination_Broadcast = new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+ public static byte[] MAC_Broadcast = new byte[] { (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0 };
+
+ public static byte[] getPayload(short opCode, byte[] senderMacAddress, byte[] senderIP, byte[] targetMacAddress,
+ byte[] targetIP) throws PacketException {
+ ARP arp = createARPPacket(opCode, senderMacAddress, senderIP, targetMacAddress, targetIP);
+ Ethernet ethernet = createEthernetPacket(senderMacAddress, targetMacAddress, arp);
+ return ethernet.serialize();
+ }
+
+ public static ARP createARPPacket(short opCode, byte[] senderMacAddress, byte[] senderIP, byte[] targetMacAddress,
+ byte[] targetIP) {
+ ARP arp = new ARP();
+ arp.setHardwareType(ARP.HW_TYPE_ETHERNET);
+ arp.setProtocolType(EtherTypes.IPv4.shortValue());
+ arp.setHardwareAddressLength((byte) 6);
+ arp.setProtocolAddressLength((byte) 4);
+ arp.setOpCode(opCode);
+ arp.setSenderHardwareAddress(senderMacAddress);
+ arp.setSenderProtocolAddress(senderIP);
+ arp.setTargetHardwareAddress(targetMacAddress);
+ arp.setTargetProtocolAddress(targetIP);
+ return arp;
+ }
+
+ public static Ethernet createEthernetPacket(byte[] sourceMAC, byte[] targetMAC, ARP arp)
+ throws PacketException {
+ Ethernet ethernet = new Ethernet();
+ ethernet.setSourceMACAddress(sourceMAC);
+ ethernet.setDestinationMACAddress(targetMAC);
+ ethernet.setEtherType(EtherTypes.ARP.shortValue());
+ ethernet.setPayload(arp);
+ return ethernet;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.arputil.internal;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import org.opendaylight.controller.liblldp.NetUtils;
+import org.opendaylight.controller.liblldp.Packet;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.md.sal.binding.api.NotificationService;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+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.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.vpnservice.mdsalutil.packet.ARP;
+import org.opendaylight.vpnservice.mdsalutil.packet.Ethernet;
+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;
+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.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+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.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+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.model.match.types.rev131026.match.Metadata;
+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.PacketProcessingService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.SendToController;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.ArpRequestReceived;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.ArpRequestReceivedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.ArpResponseReceivedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.GetMacInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.GetMacOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.GetMacOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.MacChangedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpRequestInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpRequestInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpResponseInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.interfaces.InterfaceAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.BaseIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexOutput;
+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.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+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 com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import com.google.common.util.concurrent.SettableFuture;
+
+public class ArpUtilImpl implements OdlArputilService,
+ PacketProcessingListener, AutoCloseable {
+
+ private static final String FAILED_TO_GET_SRC_IP_FOR_INTERFACE = "Failed to get src ip for %s";
+
+ private static final String FAILED_TO_GET_SRC_MAC_FOR_INTERFACE = "Failed to get src mac for interface %s iid %s ";
+
+ private static final String FAILED_TO_SEND_ARP_REQ_FOR_INTERFACE = "failed to send arp req for interface ";
+
+ private static final String UNKNOWN_IP_ADDRESS_SUPPLIED = "unknown ip address supplied";
+
+ private static final String NODE_CONNECTOR_NOT_FOUND_ERROR = "Node connector id not found for interface %s";
+
+ private static final String DPN_NOT_FOUND_ERROR = "dpn not found for interface %s ";
+
+ private static final short ARP_REQUEST_OP = (short) 1;
+
+ private static final short ARP_RESPONSE_OP = (short) 2;
+
+ private static final short ETH_TYPE_ARP = 0x0806;
+
+ private static final Logger LOGGER = LoggerFactory
+ .getLogger(ArpUtilImpl.class);
+
+ static OdlInterfaceRpcService intfRpc;
+
+ ExecutorService threadPool = Executors.newFixedThreadPool(1);
+
+ DataBroker dataBroker;
+ PacketProcessingService packetProcessingService;
+ NotificationPublishService notificationPublishService;
+ NotificationService notificationService;
+ IMdsalApiManager mdsalMgr;
+
+ RpcProviderRegistry rpc;
+ ListenerRegistration<ArpUtilImpl> listenerRegistration;
+
+ ConcurrentMap<String, String> macsDB = new ConcurrentHashMap<>();
+ ConcurrentMap<String, SettableFuture<RpcResult<GetMacOutput>>> getMacFutures = new ConcurrentHashMap<>();
+
+ public ArpUtilImpl(DataBroker db,
+ PacketProcessingService packetProcessingService,
+ NotificationPublishService notificationPublishService,
+ NotificationService notificationService,
+ IMdsalApiManager mdsalApiManager,
+ RpcProviderRegistry rpc) {
+
+ this.dataBroker = db;
+ this.packetProcessingService = packetProcessingService;
+ this.notificationPublishService = notificationPublishService;
+ this.mdsalMgr = mdsalApiManager;
+ this.notificationService = notificationService;
+ this.rpc = rpc;
+ listenerRegistration = notificationService
+ .registerNotificationListener(this);
+ LOGGER.info("ArpUtil Manager Initialized ");
+ }
+
+ OdlInterfaceRpcService getInterfaceRpcService() {
+ if (intfRpc == null ) {
+ intfRpc = rpc.getRpcService(OdlInterfaceRpcService.class);
+ }
+ return intfRpc;
+ }
+
+ @Override
+ public void close() throws Exception {
+ listenerRegistration.close();
+ LOGGER.trace("ArpUtil manager Closed");
+ }
+
+ String getIpAddressInString(IpAddress ipAddress)
+ throws UnknownHostException {
+ return InetAddress.getByName(ipAddress.getIpv4Address().getValue())
+ .getHostAddress();
+ }
+
+ public Future<RpcResult<GetMacOutput>> getMac(GetMacInput input) {
+
+ try {
+ final String dstIpAddress = getIpAddressInString(input
+ .getIpaddress());
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace("getMac rpc invoked for ip " + dstIpAddress);
+ }
+ if (getMacFutures.get(dstIpAddress) != null) {
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info("get mac already in progress for the ip "
+ + dstIpAddress);
+ }
+ return getMacFutures.get(dstIpAddress);
+ }
+ SendArpRequestInputBuilder builder = new SendArpRequestInputBuilder()
+ .setInterfaceAddress(input.getInterfaceAddress())
+ .setIpaddress(input.getIpaddress());
+ Future<RpcResult<Void>> arpReqFt = sendArpRequest(builder.build());
+ final SettableFuture<RpcResult<GetMacOutput>> ft = SettableFuture
+ .create();
+
+ Futures.addCallback(
+ JdkFutureAdapters.listenInPoolThread(arpReqFt, threadPool),
+ new FutureCallback<RpcResult<Void>>() {
+ @Override
+ public void onFailure(Throwable e) {
+ RpcResultBuilder<GetMacOutput> resultBuilder = RpcResultBuilder
+ .<GetMacOutput> failed().withError(
+ ErrorType.APPLICATION,
+ e.getMessage(), e);
+ ft.set(resultBuilder.build());
+ }
+
+ @Override
+ public void onSuccess(RpcResult<Void> result) {
+ LOGGER.trace("Successfully sent the arp pkt out for ip "
+ + dstIpAddress);
+ }
+ });
+
+ getMacFutures.put(dstIpAddress, ft);
+ return ft;
+ } catch (Exception e) {
+ LOGGER.trace("failed to handle getMac request for {} {}",
+ input.getIpaddress(), e);
+ RpcResultBuilder<GetMacOutput> resultBuilder = RpcResultBuilder
+ .<GetMacOutput> failed().withError(ErrorType.APPLICATION,
+ e.getMessage(), e);
+ return Futures.immediateFuture(resultBuilder.build());
+ }
+ }
+
+ byte[] getIpAddressBytes(IpAddress ip) throws UnknownHostException {
+ return InetAddress.getByName(ip.getIpv4Address().getValue())
+ .getAddress();
+ }
+
+ @Override
+ public Future<RpcResult<Void>> sendArpRequest(
+ SendArpRequestInput arpReqInput) {
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace("rpc sendArpRequest invoked for ip "
+ + arpReqInput.getIpaddress());
+ }
+ BigInteger dpnId;
+ long groupId;
+ byte payload[];
+ String interfaceName = null;
+ byte srcIpBytes[];
+ byte[] dstIpBytes = null;
+
+ RpcResultBuilder<Void> failureBuilder = RpcResultBuilder
+ .<Void> failed();
+ RpcResultBuilder<Void> successBuilder = RpcResultBuilder
+ .<Void> success();
+
+ try {
+ dstIpBytes = getIpAddressBytes(arpReqInput.getIpaddress());
+ } catch (Exception e) {
+ failureBuilder.withError(ErrorType.APPLICATION,
+ UNKNOWN_IP_ADDRESS_SUPPLIED);
+ return Futures.immediateFuture(failureBuilder.build());
+ }
+
+ int localErrorCount = 0;
+ for (InterfaceAddress interfaceAddress : arpReqInput
+ .getInterfaceAddress()) {
+ try {
+ interfaceName = interfaceAddress.getInterface();
+ srcIpBytes = getIpAddressBytes(interfaceAddress.getIpAddress());
+
+ NodeConnectorId id = getNodeConnectorFromInterfaceName(interfaceName);
+
+ GetPortFromInterfaceOutput portResult = getPortFromInterface(interfaceName);
+ dpnId = portResult.getDpid();
+ Long portid = portResult.getPortno();
+ checkArgument(null != dpnId && BigInteger.ZERO != dpnId,
+ DPN_NOT_FOUND_ERROR, interfaceName);
+
+ NodeConnectorRef ref = MDSALUtil.getNodeConnRef(dpnId,
+ portid.toString());
+ checkNotNull(ref, NODE_CONNECTOR_NOT_FOUND_ERROR, interfaceName);
+
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace(
+ "sendArpRequest received dpnId {} out interface {}",
+ dpnId, interfaceName);
+ }
+ byte srcMac[] = MDSALUtil.getMacAddressForNodeConnector(
+ dataBroker,
+ (InstanceIdentifier<NodeConnector>) ref.getValue());
+ checkNotNull(srcMac, FAILED_TO_GET_SRC_MAC_FOR_INTERFACE,
+ interfaceName, ref.getValue());
+ checkNotNull(srcIpBytes, FAILED_TO_GET_SRC_IP_FOR_INTERFACE,
+ interfaceName);
+
+ payload = ArpPacketUtil.getPayload(ARP_REQUEST_OP, srcMac,
+ srcIpBytes, ArpPacketUtil.EthernetDestination_Broadcast,
+ dstIpBytes);
+
+ sendPacketOut(dpnId, payload, ref);
+
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace("sent arp request for "
+ + arpReqInput.getIpaddress());
+ }
+ } catch (Throwable e) {
+ LOGGER.trace("failed to send arp req for {} on interface {}",
+ arpReqInput.getIpaddress(), interfaceName);
+
+ failureBuilder
+ .withError(ErrorType.APPLICATION,
+ FAILED_TO_SEND_ARP_REQ_FOR_INTERFACE
+ + interfaceName, e);
+ successBuilder
+ .withError(ErrorType.APPLICATION,
+ FAILED_TO_SEND_ARP_REQ_FOR_INTERFACE
+ + interfaceName, e);
+ localErrorCount++;
+ }
+ }
+ if (localErrorCount == arpReqInput.getInterfaceAddress().size()) {
+ // All the requests failed
+ return Futures.immediateFuture(failureBuilder.build());
+ }
+ return Futures.immediateFuture(successBuilder.build());
+ }
+
+ public Future<RpcResult<Void>> sendPacketOut(BigInteger dpnId,
+ byte[] payload, NodeConnectorRef ref) {
+
+ NodeConnectorRef nodeConnectorRef = MDSALUtil.getNodeConnRef(dpnId,
+ "0xfffffffd");
+ return packetProcessingService
+ .transmitPacket(new TransmitPacketInputBuilder()
+ .setPayload(payload)
+ .setNode(
+ new NodeRef(InstanceIdentifier
+ .builder(Nodes.class)
+ .child(Node.class,
+ new NodeKey(new NodeId(
+ "openflow:" + dpnId)))
+ .toInstance()))
+ .setIngress(nodeConnectorRef).setEgress(ref).build());
+ }
+
+ @Override
+ public Future<RpcResult<Void>> sendArpResponse(SendArpResponseInput input) {
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace("sendArpResponse rpc invoked");
+ }
+ BigInteger dpnId;
+ long groupId;
+ byte payload[];
+
+ try {
+ String interfaceName = input.getInterface();
+ GetPortFromInterfaceOutput portResult = getPortFromInterface(interfaceName);
+ dpnId = portResult.getDpid();
+ Long portid = portResult.getPortno();
+ NodeConnectorRef ref = MDSALUtil.getNodeConnRef(dpnId,
+ portid.toString());
+ checkArgument(null != dpnId && BigInteger.ZERO != dpnId,
+ DPN_NOT_FOUND_ERROR, interfaceName);
+ checkNotNull(ref, NODE_CONNECTOR_NOT_FOUND_ERROR, interfaceName);
+
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace(
+ "sendArpRequest received dpnId {} out interface {}",
+ dpnId, interfaceName);
+ }
+
+ byte[] srcIpBytes = getIpAddressBytes(input.getSrcIpAddress());
+ byte[] dstIpBytes = getIpAddressBytes(input.getIpaddress());
+ byte srcMac[] = MDSALUtil.getMacAddressForNodeConnector(dataBroker,
+ (InstanceIdentifier<NodeConnector>) ref.getValue());
+ byte[] dstMac = NWUtil.parseMacAddress(input.getMacaddress()
+ .getValue());
+ checkNotNull(srcIpBytes, FAILED_TO_GET_SRC_IP_FOR_INTERFACE,
+ interfaceName);
+ payload = ArpPacketUtil.getPayload(ARP_RESPONSE_OP, srcMac, srcIpBytes,
+ dstMac, dstIpBytes);
+
+ sendPacketOut(dpnId, payload, ref);
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace("sent the arp response for "
+ + input.getSrcIpAddress());
+ }
+ } catch (Throwable e) {
+ LOGGER.trace("failed to send arp response for {} {}",
+ input.getSrcIpAddress(), e);
+ return RpcResultBuilder.<Void> failed()
+ .withError(ErrorType.APPLICATION, e.getMessage(), e)
+ .buildFuture();
+ }
+ RpcResultBuilder<Void> rpcResultBuilder = RpcResultBuilder.success();
+ return Futures.immediateFuture(rpcResultBuilder.build());
+ }
+
+ @Override
+ public void onPacketReceived(PacketReceived packetReceived) {
+ Class<? extends PacketInReason> pktInReason = packetReceived
+ .getPacketInReason();
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace("Packet Received {}", packetReceived);
+ }
+
+ if (pktInReason == SendToController.class) {
+
+ try {
+ int tableId = packetReceived.getTableId().getValue();
+
+ byte[] data = packetReceived.getPayload();
+ Ethernet ethernet = new Ethernet();
+
+ ethernet.deserialize(data, 0, data.length
+ * NetUtils.NumBitsInAByte);
+ if (ethernet.getEtherType() != ETH_TYPE_ARP) {
+ return;
+ }
+
+ Packet pkt = ethernet.getPayload();
+ ARP arp = (ARP) pkt;
+ InetAddress srcInetAddr = InetAddress.getByAddress(arp
+ .getSenderProtocolAddress());
+ InetAddress dstInetAddr = InetAddress.getByAddress(arp
+ .getTargetProtocolAddress());
+ byte[] srcMac = ethernet.getSourceMACAddress();
+
+ NodeConnectorRef ref = packetReceived.getIngress();
+
+ Metadata metadata = packetReceived.getMatch().getMetadata();
+ String interfaceName = getInterfaceName(ref,metadata, dataBroker);
+
+ checkAndFireMacChangedNotification(interfaceName, srcInetAddr,
+ srcMac);
+
+ macsDB.put(interfaceName + "-" + srcInetAddr.getHostAddress(),
+ NWUtil.toStringMacAddress(srcMac));
+
+ if (arp.getOpCode() == ARP_REQUEST_OP) {
+ fireArpReqRecvdNotification(interfaceName, srcInetAddr,
+ srcMac, dstInetAddr, tableId);
+ } else {
+ fireArpRespRecvdNotification(interfaceName, srcInetAddr,
+ srcMac, tableId);
+ }
+ if (getMacFutures.get(srcInetAddr.getHostAddress()) != null) {
+ threadPool.submit(new MacResponderTask(arp));
+ }
+
+ } catch (Throwable e) {
+ LOGGER.trace("Failed to decode packet: {}", e);
+ }
+ }
+ }
+
+ GetPortFromInterfaceOutput getPortFromInterface(String interfaceName) throws Throwable {
+ GetPortFromInterfaceInputBuilder getPortFromInterfaceInputBuilder = new GetPortFromInterfaceInputBuilder();
+ getPortFromInterfaceInputBuilder.setIntfName(interfaceName);;
+ Future<RpcResult<GetPortFromInterfaceOutput>> portFromInterface = intfRpc.getPortFromInterface(getPortFromInterfaceInputBuilder.build());
+ GetPortFromInterfaceOutput result = portFromInterface.get().getResult();
+ LOGGER.trace("getPortFromInterface rpc result is {} ", result);
+ if (result != null) {
+ LOGGER.trace("getPortFromInterface rpc result is {} {} ", result.getDpid(), result.getPortno());
+ }
+ return result;
+ }
+
+ private String getInterfaceName(NodeConnectorRef ref, Metadata metadata, DataBroker dataBroker2) throws Throwable {
+ LOGGER.debug("metadata received is {} ", metadata);
+
+ GetInterfaceFromIfIndexInputBuilder ifIndexInputBuilder = new GetInterfaceFromIfIndexInputBuilder();
+ BigInteger lportTag = MetaDataUtil.getLportFromMetadata(metadata.getMetadata());
+
+ ifIndexInputBuilder.setIfIndex(lportTag.intValue());
+ GetInterfaceFromIfIndexInput input = ifIndexInputBuilder.build();
+ OdlInterfaceRpcService intfRpc = getInterfaceRpcService();
+
+ Future<RpcResult<GetInterfaceFromIfIndexOutput>> interfaceFromIfIndex = intfRpc.getInterfaceFromIfIndex(input);
+ GetInterfaceFromIfIndexOutput interfaceFromIfIndexOutput = interfaceFromIfIndex.get().getResult();
+ return interfaceFromIfIndexOutput.getInterfaceName();
+ }
+
+ class MacResponderTask implements Runnable {
+ ARP arp;
+
+ MacResponderTask(ARP arp) {
+ this.arp = arp;
+ }
+
+ @Override
+ public void run() {
+ InetAddress srcAddr;
+ GetMacOutputBuilder outputBuilder;
+ String srcMac;
+ SettableFuture<RpcResult<GetMacOutput>> future = null;
+ RpcResultBuilder<GetMacOutput> resultBuilder;
+ try {
+ srcAddr = InetAddress.getByAddress(arp
+ .getSenderProtocolAddress());
+ srcMac = NWUtil.toStringMacAddress(arp
+ .getSenderHardwareAddress());
+ future = getMacFutures.remove(srcAddr.getHostAddress());
+ if (future == null) {
+ LOGGER.trace("There are no pending mac requests.");
+ return;
+ }
+ outputBuilder = new GetMacOutputBuilder()
+ .setMacaddress(new PhysAddress(srcMac));
+ resultBuilder = RpcResultBuilder.success(outputBuilder.build());
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace("sent the mac response for ip {}",
+ srcAddr.getHostAddress());
+ }
+ } catch (Exception e) {
+ LOGGER.trace("failed to send mac response {} ", e);
+ resultBuilder = RpcResultBuilder.<GetMacOutput> failed()
+ .withError(ErrorType.APPLICATION, e.getMessage(), e);
+ }
+ future.set(resultBuilder.build());
+ }
+ }
+
+ private void fireArpRespRecvdNotification(String interfaceName,
+ InetAddress inetAddr, byte[] macAddressBytes, int tableId)
+ throws InterruptedException {
+
+ IpAddress ip = new IpAddress(inetAddr.getHostAddress().toCharArray());
+ String macAddress = NWUtil.toStringMacAddress(macAddressBytes);
+ PhysAddress mac = new PhysAddress(macAddress);
+ ArpResponseReceivedBuilder builder = new ArpResponseReceivedBuilder();
+ builder.setInterface(interfaceName);
+ builder.setIpaddress(ip);
+ builder.setOfTableId((long) tableId);
+ builder.setMacaddress(mac);
+ notificationPublishService.putNotification(builder.build());
+ }
+
+ private void fireArpReqRecvdNotification(String interfaceName,
+ InetAddress srcInetAddr, byte[] srcMac, InetAddress dstInetAddr,
+ int tableId) throws InterruptedException {
+ String macAddress = NWUtil.toStringMacAddress(srcMac);
+ ArpRequestReceivedBuilder builder = new ArpRequestReceivedBuilder();
+ builder.setInterface(interfaceName);
+ builder.setOfTableId((long) tableId);
+ builder.setSrcIpaddress(new IpAddress(srcInetAddr.getHostAddress()
+ .toCharArray()));
+ builder.setDstIpaddress(new IpAddress(dstInetAddr.getHostAddress()
+ .toCharArray()));
+ builder.setSrcMac(new PhysAddress(macAddress));
+ notificationPublishService.putNotification(builder.build());
+ }
+
+ private void checkAndFireMacChangedNotification(String interfaceName,
+ InetAddress inetAddr, byte[] macAddressBytes)
+ throws InterruptedException {
+
+ IpAddress ip = new IpAddress(inetAddr.getHostAddress().toCharArray());
+ String macAddress = NWUtil.toStringMacAddress(macAddressBytes);
+ PhysAddress mac = new PhysAddress(macAddress);
+
+ if (!macAddress.equals(macsDB.get(interfaceName + "-"
+ + inetAddr.getHostAddress()))) {
+ if (LOGGER.isTraceEnabled()) {
+ LOGGER.trace("mac address changed for " + inetAddr);
+ }
+ MacChangedBuilder builder = new MacChangedBuilder();
+ builder.setInterface(interfaceName);
+ builder.setIpaddress(ip);
+ builder.setMacaddress(mac);
+ notificationPublishService.putNotification(builder.build());
+ }
+ }
+
+ private InstanceIdentifier<Interface> buildInterfaceId(String interfaceName) {
+ InstanceIdentifierBuilder<Interface> idBuilder = InstanceIdentifier
+ .builder(Interfaces.class).child(Interface.class,
+ new InterfaceKey(interfaceName));
+ InstanceIdentifier<Interface> id = idBuilder.build();
+ return id;
+ }
+
+
+ private NodeConnectorId getNodeConnectorFromInterfaceName(String interfaceName) {
+ InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> idBuilder =
+ InstanceIdentifier.builder(InterfacesState.class)
+ .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class,
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName));
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId = idBuilder.build();
+
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateOptional = MDSALUtil.read(dataBroker,
+ LogicalDatastoreType.OPERATIONAL,
+ ifStateId);
+
+ if (ifStateOptional.isPresent()) {
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState = ifStateOptional.get();
+ List<String> lowerLayerIf = ifState.getLowerLayerIf();
+ if (!lowerLayerIf.isEmpty()) {
+ return new NodeConnectorId(lowerLayerIf.get(0));
+ }
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.arputil.internal;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.md.sal.binding.api.NotificationService;
+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.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ArpUtilProvider implements BindingAwareProvider, AutoCloseable {
+
+ private static final Logger s_logger = LoggerFactory.getLogger(ArpUtilProvider.class);
+
+ RpcProviderRegistry rpcProviderRegistry;
+
+ NotificationService notificationService;
+
+ NotificationPublishService notificationPublishService;
+
+ ArpUtilImpl arpManager;
+
+ IMdsalApiManager mdsalApiManager;
+
+ BindingAwareBroker.RpcRegistration<OdlArputilService> rpcRegistration;
+
+ public ArpUtilProvider(RpcProviderRegistry rpcRegistry,
+ NotificationPublishService publishService,
+ NotificationService notificationService,
+ IMdsalApiManager iMdsalApiManager) {
+
+ this.rpcProviderRegistry = rpcRegistry;
+ this.mdsalApiManager = iMdsalApiManager;
+ this.notificationPublishService = publishService;
+ this.notificationService = notificationService;
+ }
+
+ public ArpUtilProvider() {
+ }
+
+ @Override
+ public void onSessionInitiated(final ProviderContext session){
+
+ s_logger.info( " Session Initiated for Arp Provider") ;
+
+ try {
+ DataBroker dataBroker = session.getSALService(DataBroker.class);
+ PacketProcessingService packetProcessingService =
+ session.getRpcService(PacketProcessingService.class);
+
+ arpManager = new ArpUtilImpl( dataBroker, packetProcessingService,
+ notificationPublishService, notificationService,
+ mdsalApiManager, rpcProviderRegistry) ;
+
+ rpcRegistration = rpcProviderRegistry.
+ addRpcImplementation(OdlArputilService.class, arpManager);
+ s_logger.info( " Session Initialized for Arp Provider") ;
+ }catch( Exception e) {
+ s_logger.error( "Error initializing Arp " , e );
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ rpcRegistration.close();
+ arpManager.close();
+ s_logger.info("ArpManager Manager Closed");
+ }
+}
--- /dev/null
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.impl.rev151126;
+
+import org.opendaylight.vpnservice.arputil.internal.ArpUtilProvider;
+
+public class ArputilImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.impl.rev151126.AbstractArputilImplModule {
+ public ArputilImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public ArputilImplModule(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.arputil.impl.rev151126.ArputilImplModule 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() {
+ ArpUtilProvider provider = new ArpUtilProvider(getRpcRegistryDependency(),
+ getNotificationPublishServiceDependency(),
+ getNotificationServiceDependency(),
+ getMdsalutilDependency()
+ );
+ getBrokerDependency().registerProvider(provider);
+ return provider;
+ }
+
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: arputil-impl yang module local name: arputil-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Mon Dec 07 21:19:46 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.arputil.impl.rev151126;
+public class ArputilImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.impl.rev151126.AbstractArputilImplModuleFactory {
+
+}
--- /dev/null
+module arputil-impl {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:arputil:impl";
+ prefix "arputil-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 odl-mdsalutil { prefix odl-mdsal; revision-date 2015-04-10;}
+ import ietf-inet-types { prefix inet; }
+ import ietf-yang-types { prefix yang;}
+
+ description
+ "Service definition for mdsal project";
+
+ revision "2015-11-26" {
+ description
+ "Initial revision";
+ }
+
+ identity arputil-impl {
+ base config:module-type;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case arputil-impl {
+ when "/config:modules/config:module/config:type = 'arputil-impl'";
+ container broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-broker-osgi-registry;
+ }
+ }
+ }
+ container rpc-registry {
+ 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 notification-publish-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding-impl:binding-new-notification-publish-service;
+ }
+ }
+ }
+ container notification-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding-impl:binding-new-notification-service;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>arputil-aggregator</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <name>arputil</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>arputil-api</module>
+ <module>arputil-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>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: --><!--
+Copyright (c) 2015 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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>bgpmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <maven.javadoc.skip>true</maven.javadoc.skip>
+ </properties>
+</project>
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.bgpmanager.api;
+
+import java.util.Collection;
+
+public interface IBgpManager {
+
+ /**
+ *
+ * @param rd
+ * @param importRts
+ * @param exportRts
+ */
+ public void addVrf(String rd, Collection<String> importRts, Collection<String> exportRts) throws Exception;
+
+ /**
+ *
+ * @param rd
+ */
+ public void deleteVrf(String rd) throws Exception;
+
+ /**
+ *
+ * @param rd
+ * @param prefix
+ * @param nextHop
+ * @param vpnLabel
+ */
+ public void addPrefix(String rd, String prefix, String nextHop, int vpnLabel) throws Exception;
+
+ /**
+ *
+ * @param rd
+ * @param prefix
+ */
+ public void deletePrefix(String rd, String prefix) throws Exception;
+
+ /**
+ *
+ * @param fileName
+ * @param logLevel
+ */
+ public void setQbgpLog(String fileName, String logLevel) throws Exception;
+
+ /**
+ * @param rd
+ * @param prefix
+ * @param nextHop
+ * @param vpnLabel
+ */
+ public void advertisePrefix(String rd, String prefix, String nextHop, int vpnLabel) throws Exception;
+
+ /**
+ *
+ * @param rd
+ * @param prefix
+ */
+ public void withdrawPrefix(String rd, String prefix) throws Exception;
+
+
+ public String getDCGwIP();
+
+}
--- /dev/null
+module bgpmanager-api {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:bgpmanager:api";
+ prefix "bgpmgr-api";
+
+ import config { prefix config; revision-date 2013-04-05; }
+
+ description
+ "Service definition for bgpmanager project";
+
+ revision "2015-04-20" {
+ description
+ "Initial revision";
+ }
+
+ identity bgpmanager-api {
+ base "config:service-type";
+ config:java-class "org.opendaylight.bgpmanager.api.IBgpManager";
+ }
+}
\ 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) 2015 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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>bgpmanager-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+ <properties>
+ <codahale.metrics.version>3.0.1</codahale.metrics.version>
+ </properties>
+ <dependencies>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgpmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>model-bgp</artifactId>
+ <version>${model.bgp.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>fibmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.thrift</groupId>
+ <artifactId>libthrift</artifactId>
+ <version>0.9.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>vpnmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>itm-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+
+ <!--Dependencies for Unit Test -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <version>${mdsal.version}</version>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.console</artifactId>
+ <version>3.0.3</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>log4j</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>com.codahale.metrics</groupId>
+ <artifactId>metrics-core</artifactId>
+ <version>3.0.1</version>
+
+ </dependency>
+ <dependency>
+ <groupId>com.codahale.metrics</groupId>
+ <artifactId>metrics-graphite</artifactId>
+ <version>3.0.1</version>
+
+ </dependency>
+
+ </dependencies>
+
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright (c) 2015 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:bgpmanager:api?module=bgpmanager-api&revision=2015-04-20</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:bgpmanager:impl?module=bgpmanager-impl&revision=2015-03-26</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:vpnservice:itm?module=itm&revision=2015-07-01</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:bgpmanager:impl">prefix:bgpmanager-impl</type>
+ <name>bgpmanager-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>
+ <!--<itm>
+ <type xmlns:itm="urn:opendaylight:vpnservice:itm">itm:itm</type>
+ <name>itm</name>
+ </itm> -->
+ </module>
+ </modules>
+ <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <service>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:bgpmanager:api">prefix:bgpmanager-api</type>
+ <instance>
+ <name>bgpmanager</name>
+ <provider>/modules/module[type='bgpmanager-impl'][name='bgpmanager-default']</provider>
+ </instance>
+ </service>
+ </services>
+ </data>
+ </configuration>
+</snapshot>
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * AbstractDataChangeListener implemented basic {@link DataChangeListener} processing for
+ * VPN related Data Objects.
+ */
+public abstract class AbstractDataChangeListener <T extends DataObject> implements DataChangeListener {
+
+ protected final Class<T> clazz;
+
+ public AbstractDataChangeListener(Class<T> clazz) {
+ this.clazz = Preconditions.checkNotNull(clazz, "Class can not be null!");
+ }
+
+ @Override
+ public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
+ Preconditions.checkNotNull(changeEvent,"Async ChangeEvent can not be null!");
+
+ /* All DataObjects for create */
+ final Map<InstanceIdentifier<?>, DataObject> createdData = changeEvent.getCreatedData() != null
+ ? changeEvent.getCreatedData() : Collections.<InstanceIdentifier<?>, DataObject> emptyMap();
+ /* All DataObjects for remove */
+ final Set<InstanceIdentifier<?>> removeData = changeEvent.getRemovedPaths() != null
+ ? changeEvent.getRemovedPaths() : Collections.<InstanceIdentifier<?>> emptySet();
+ /* All DataObjects for updates */
+ final Map<InstanceIdentifier<?>, DataObject> updateData = changeEvent.getUpdatedData() != null
+ ? changeEvent.getUpdatedData() : Collections.<InstanceIdentifier<?>, DataObject> emptyMap();
+ /* All Original DataObjects */
+ final Map<InstanceIdentifier<?>, DataObject> originalData = changeEvent.getOriginalData() != null
+ ? changeEvent.getOriginalData() : Collections.<InstanceIdentifier<?>, DataObject> emptyMap();
+
+ this.createData(createdData);
+ this.updateData(updateData, originalData);
+ this.removeData(removeData, originalData);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void createData(final Map<InstanceIdentifier<?>, DataObject> createdData) {
+ final Set<InstanceIdentifier<?>> keys = createdData.keySet() != null
+ ? createdData.keySet() : Collections.<InstanceIdentifier<?>> emptySet();
+ for (InstanceIdentifier<?> key : keys) {
+ if (clazz.equals(key.getTargetType())) {
+ InstanceIdentifier<T> createKeyIdent = key.firstIdentifierOf(clazz);
+ final Optional<DataObject> value = Optional.of(createdData.get(key));
+ if (value.isPresent()) {
+ this.add(createKeyIdent, (T)value.get());
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void updateData(final Map<InstanceIdentifier<?>, DataObject> updateData,
+ final Map<InstanceIdentifier<?>, DataObject> originalData) {
+
+ final Set<InstanceIdentifier<?>> keys = updateData.keySet() != null
+ ? updateData.keySet() : Collections.<InstanceIdentifier<?>> emptySet();
+ for (InstanceIdentifier<?> key : keys) {
+ if (clazz.equals(key.getTargetType())) {
+ InstanceIdentifier<T> updateKeyIdent = key.firstIdentifierOf(clazz);
+ final Optional<DataObject> value = Optional.of(updateData.get(key));
+ final Optional<DataObject> original = Optional.of(originalData.get(key));
+ if (value.isPresent() && original.isPresent()) {
+ this.update(updateKeyIdent, (T)original.get(), (T)value.get());
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void removeData(final Set<InstanceIdentifier<?>> removeData,
+ final Map<InstanceIdentifier<?>, DataObject> originalData) {
+
+ for (InstanceIdentifier<?> key : removeData) {
+ if (clazz.equals(key.getTargetType())) {
+ final InstanceIdentifier<T> ident = key.firstIdentifierOf(clazz);
+ final DataObject removeValue = originalData.get(key);
+ this.remove(ident, (T)removeValue);
+ }
+ }
+ }
+
+ protected abstract void remove(InstanceIdentifier<T> identifier, T del);
+
+ protected abstract void update(InstanceIdentifier<T> identifier, T original, T update);
+
+ protected abstract void add(InstanceIdentifier<T> identifier, T add);
+
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager;
+
+import com.google.common.base.Optional;
+
+import java.util.*;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.*;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.opendaylight.bgpmanager.commands.ClearBgpCli;
+import org.opendaylight.bgpmanager.thrift.gen.*;
+import org.opendaylight.bgpmanager.thrift.client.*;
+import org.opendaylight.bgpmanager.thrift.server.*;
+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.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+//import org.opendaylight.vpnservice.itm.api.IITMProvider;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.*;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.*;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.*;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.FibEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntry;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BgpConfigurationManager {
+ private static final Logger LOG =
+ LoggerFactory.getLogger(BgpConfigurationManager.class);
+ private static DataBroker broker;
+ private static FibDSWriter fib;
+ private boolean restarting = false;
+ private static Bgp config;
+ private static BgpRouter bgpRouter;
+ private static BgpThriftService updateServer;
+
+ private static final String DEF_LOGFILE = "/var/log/bgp_debug.log";
+ private static final String DEF_LOGLEVEL = "errors";
+ private static final String UPDATE_PORT = "bgp.thrift.service.port";
+ private static final String CONFIG_HOST = "vpnservice.bgpspeaker.host.name";
+ private static final String CONFIG_PORT = "vpnservice.bgpspeaker.thrift.port";
+ private static final String DEF_UPORT = "6644";
+ private static final String DEF_CHOST = "127.0.0.1";
+ private static final String DEF_CPORT = "7644";
+ private static final String SDNC_BGP_MIP = "sdnc_bgp_mip";
+ private static final String CLUSTER_CONF_FILE = "/cluster/etc/cluster.conf";
+ private static final Timer ipActivationCheckTimer = new Timer();
+
+ // to have stale FIB map (RD, Prefix)
+ // number of seconds wait for route sync-up between ODL and BGP.
+ private static final int BGP_RESTART_ROUTE_SYNC_SEC = 360;
+
+ static String odlThriftIp = "127.0.0.1";
+ private static String cHostStartup;
+ private static String cPortStartup;
+ private static CountDownLatch initer = new CountDownLatch(1);
+ //static IITMProvider itmProvider;
+ public static BgpManager bgpManager;
+ //map<rd, map<prefix/len, nexthop/label>>
+ private static Map<String, Map<String, String>> staledFibEntriesMap = new ConcurrentHashMap<>();
+
+ private static final Class[] reactors =
+ {
+ ConfigServerReactor.class, AsIdReactor.class,
+ GracefulRestartReactor.class, LoggingReactor.class,
+ NeighborsReactor.class, UpdateSourceReactor.class,
+ EbgpMultihopReactor.class, AddressFamiliesReactor.class,
+ NetworksReactor.class, VrfsReactor.class, BgpReactor.class
+ };
+
+ private ListenerRegistration<DataChangeListener>[] registrations;
+
+ private Object createListener(Class<?> cls) {
+ Constructor<?> ctor;
+ Object obj = null;
+
+ try {
+ ctor= cls.getConstructor(BgpConfigurationManager.class);
+ obj = ctor.newInstance(this);
+ } catch (Exception e) {
+ LOG.error("Failed to create listener object", e);
+ }
+ return obj;
+ }
+
+ private void registerCallbacks() {
+ String emsg = "Failed to register listener";
+ registrations = (ListenerRegistration<DataChangeListener>[])
+ new ListenerRegistration[reactors.length];
+ InstanceIdentifier<?> iid = InstanceIdentifier.create(Bgp.class);
+ for (int i = 0; i < reactors.length; i++) {
+ DataChangeListener dcl =
+ (DataChangeListener) createListener(reactors[i]);
+ String dclName = dcl.getClass().getName();
+ try {
+ registrations[i] = broker.registerDataChangeListener(
+ LogicalDatastoreType.CONFIGURATION,
+ iid, dcl, DataChangeScope.SUBTREE);
+ } catch (Exception e) {
+ LOG.error(emsg, e);
+ throw new IllegalStateException(emsg+" "+dclName, e);
+ }
+ }
+ }
+
+ public void close() {
+ if (updateServer != null) {
+ updateServer.stop();
+ }
+ }
+
+ private boolean configExists() {
+ InstanceIdentifier.InstanceIdentifierBuilder<Bgp> iib =
+ InstanceIdentifier.builder(Bgp.class);
+ InstanceIdentifier<Bgp> iid = iib.build();
+ Optional<Bgp> b = BgpUtil.read(broker,
+ LogicalDatastoreType.CONFIGURATION, iid);
+ return b.isPresent();
+ }
+
+ private String getProperty(String var, String def) {
+ Bundle b = FrameworkUtil.getBundle(BgpManager.class);
+ if (b == null) {
+ return def;
+ }
+ BundleContext context = b.getBundleContext();
+ if (context == null) {
+ return def;
+ }
+ String s = context.getProperty(var);
+ return (s == null ? def : s);
+ }
+
+ public BgpConfigurationManager(BgpManager bgpMgr) {
+ broker = bgpMgr.getBroker();
+ fib = bgpMgr.getFibWriter();
+ //itmProvider = bgpMgr.getItmProvider();
+ // there must be a good way to detect that we're restarting.
+ // but for now infer it from the existance of config
+ restarting = configExists();
+ bgpManager = bgpMgr;
+ bgpRouter = BgpRouter.getInstance();
+ String uPort = getProperty(UPDATE_PORT, DEF_UPORT);
+ cHostStartup = getProperty(CONFIG_HOST, DEF_CHOST);
+ cPortStartup = getProperty(CONFIG_PORT, DEF_CPORT);
+ VtyshCli.setHostAddr(cHostStartup);
+ ClearBgpCli.setHostAddr(cHostStartup);
+ LOG.info("UpdateServer at localhost:"+uPort+" ConfigServer at "
+ +cHostStartup+":"+cPortStartup);
+ updateServer = new BgpThriftService(Integer.parseInt(uPort), bgpMgr);
+ updateServer.start();
+ readOdlThriftIpForBgpCommunication();
+ registerCallbacks();
+
+ // this shouldn't be done. config client must connect in
+ // response to config; but connecting at startup to a default
+ // host is legacy behavior.
+ if (!restarting) {
+ bgpRouter.connect(cHostStartup, Integer.parseInt(cPortStartup));
+ }
+ LOG.info("BGP Configuration manager initialized");
+ initer.countDown();
+ }
+
+ public Bgp get() {
+ return config;
+ }
+
+ private static final String addWarn =
+ "Config store updated; undo with Delete if needed.";
+ private static final String delWarn =
+ "Config store updated; undo with Add if needed.";
+ private static final String updWarn =
+ "Update operation not supported; Config store updated;"
+ +" restore with another Update if needed.";
+
+ public class ConfigServerReactor
+ extends AbstractDataChangeListener<ConfigServer>
+ implements AutoCloseable {
+ private static final String yangObj = "config-server ";
+ public ConfigServerReactor() {
+ super(ConfigServer.class);
+ }
+
+ protected synchronized void
+ add(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
+ LOG.debug("received bgp connect config host {}", val.getHost().getValue());
+ try {
+ initer.await();
+ } catch (Exception e) {
+ }
+ LOG.debug("issueing bgp router connect to host {}", val.getHost().getValue());
+ synchronized(BgpConfigurationManager.this) {
+ boolean res = bgpRouter.connect(val.getHost().getValue(),
+ val.getPort().intValue());
+ if (!res) {
+ LOG.error(yangObj + "Add failed; "+addWarn);
+ }
+ }
+ }
+
+ protected synchronized void
+ remove(InstanceIdentifier<ConfigServer> iid, ConfigServer val) {
+ LOG.debug("received bgp disconnect");
+ synchronized(BgpConfigurationManager.this) {
+ bgpRouter.disconnect();
+ }
+ }
+
+ protected void update(InstanceIdentifier<ConfigServer> iid,
+ ConfigServer oldval, ConfigServer newval) {
+ LOG.error(yangObj + updWarn);
+ }
+
+ public void close() {
+ int i;
+ for (i=0 ; i < reactors.length ; i++) {
+ if (reactors[i] == ConfigServerReactor.class) {
+ break;
+ }
+ }
+ registrations[i].close();
+ }
+ }
+
+ private BgpRouter getClient(String yangObj) {
+ if (bgpRouter == null) {
+ LOG.warn(yangObj+": configuration received when BGP is inactive");
+ }
+ return bgpRouter;
+ }
+
+ public class AsIdReactor
+ extends AbstractDataChangeListener<AsId>
+ implements AutoCloseable {
+
+ private static final String yangObj = "as-id ";
+
+ public AsIdReactor() {
+ super(AsId.class);
+ }
+
+ protected synchronized void
+ add(InstanceIdentifier<AsId> iid, AsId val) {
+ LOG.debug("received add router config asNum {}", val.getLocalAs().intValue());
+ synchronized(BgpConfigurationManager.this) {
+ BgpRouter br = getClient(yangObj);
+ if (br == null) {
+ return;
+ }
+ int asNum = val.getLocalAs().intValue();
+ Ipv4Address routerId = val.getRouterId();
+ Long spt = val.getStalepathTime();
+ Boolean afb = val.isAnnounceFbit();
+ String rid = (routerId == null) ? "" : routerId.getValue();
+ int stalepathTime = (spt == null) ? 90 : spt.intValue();
+ boolean announceFbit = (afb == null) ? false : afb.booleanValue();
+ try {
+ br.startBgp(asNum, rid, stalepathTime, announceFbit);
+ if (bgpManager.getBgpCounters() == null) {
+ bgpManager.startBgpCountersTask();
+ }
+ } catch (BgpRouterException bre) {
+ if (bre.getErrorCode() == BgpRouterException.BGP_ERR_ACTIVE) {
+ LOG.error(yangObj+"Add requested when BGP is already active");
+ } else {
+ LOG.error(yangObj+"Add received exception: \""
+ +bre+"\"; "+addWarn);
+ }
+ } catch (Exception e) {
+ LOG.error(yangObj+"Add received exception: \""+e+"\"; "+addWarn);
+ }
+ }
+ }
+
+ protected synchronized void
+ remove(InstanceIdentifier<AsId> iid, AsId val) {
+ LOG.debug("received delete router config asNum {}", val.getLocalAs().intValue());
+ synchronized(BgpConfigurationManager.this) {
+ BgpRouter br = getClient(yangObj);
+ if (br == null) {
+ return;
+ }
+ int asNum = val.getLocalAs().intValue();
+ try {
+ br.stopBgp(asNum);
+ } catch (Exception e) {
+ LOG.error(yangObj+" Delete received exception: \""+e+"\"; "+delWarn);
+ }
+ if (bgpManager.getBgpCounters() != null) {
+ bgpManager.stopBgpCountersTask();
+ }
+ }
+ }
+
+ protected void update(InstanceIdentifier<AsId> iid,
+ AsId oldval, AsId newval) {
+ LOG.error(yangObj + updWarn);
+ }
+
+ public void close() {
+ int i;
+ for (i=0 ; i < reactors.length ; i++) {
+ if (reactors[i] == AsIdReactor.class) {
+ break;
+ }
+ }
+ registrations[i].close();
+ }
+ }
+
+ public class GracefulRestartReactor
+ extends AbstractDataChangeListener<GracefulRestart>
+ implements AutoCloseable {
+
+ private static final String yangObj = "graceful-restart ";
+
+ public GracefulRestartReactor() {
+ super(GracefulRestart.class);
+ }
+
+ protected synchronized void
+ add(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
+ synchronized(BgpConfigurationManager.this) {
+ BgpRouter br = getClient(yangObj);
+ if (br == null) {
+ return;
+ }
+ try {
+ br.addGracefulRestart(val.getStalepathTime().intValue());
+ } catch (Exception e) {
+ LOG.error(yangObj+"Add received exception: \""+e+"\"; "+addWarn);
+ }
+ }
+ }
+
+ protected synchronized void
+ remove(InstanceIdentifier<GracefulRestart> iid, GracefulRestart val) {
+ LOG.debug("received delete GracefulRestart config val {}", val.getStalepathTime().intValue());
+ synchronized(BgpConfigurationManager.this) {
+ BgpRouter br = getClient(yangObj);
+ if (br == null) {
+ return;
+ }
+ try {
+ br.delGracefulRestart();
+ } catch (Exception e) {
+ LOG.error(yangObj+" Delete received exception: \""+e+"\"; "
+ +delWarn);
+ }
+ }
+ }
+
+ protected void update(InstanceIdentifier<GracefulRestart> iid,
+ GracefulRestart oldval, GracefulRestart newval) {
+ LOG.debug("received update GracefulRestart config val {}", newval.getStalepathTime().intValue());
+ synchronized(BgpConfigurationManager.this) {
+ BgpRouter br = getClient(yangObj);
+ if (br == null) {
+ return;
+ }
+ try {
+ br.addGracefulRestart(newval.getStalepathTime().intValue());
+ } catch (Exception e) {
+ LOG.error(yangObj+"update received exception: \""+e+"\"; "+addWarn);
+ }
+ }
+ }
+
+ public void close() {
+ int i;
+ for (i=0 ; i < reactors.length ; i++) {
+ if (reactors[i] == GracefulRestartReactor.class) {
+ break;
+ }
+ }
+ registrations[i].close();
+ }
+ }
+
+ public class LoggingReactor
+ extends AbstractDataChangeListener<Logging>
+ implements AutoCloseable {
+
+ private static final String yangObj = "logging ";
+
+ public LoggingReactor() {
+ super(Logging.class);
+ }
+
+ protected synchronized void
+ add(InstanceIdentifier<Logging> iid, Logging val) {
+ synchronized(BgpConfigurationManager.this) {
+ BgpRouter br = getClient(yangObj);
+ if (br == null) {
+ return;
+ }
+ try {
+ br.setLogging(val.getFile(),val.getLevel());
+ } catch (Exception e) {
+ LOG.error(yangObj+"Add received exception: \""+e+"\"; "
+ +addWarn);
+ }
+ }
+ }
+
+ protected synchronized void
+ remove(InstanceIdentifier<Logging> iid, Logging val) {
+ LOG.debug("received remove Logging config val {}", val.getLevel());
+ synchronized(BgpConfigurationManager.this) {
+ BgpRouter br = getClient(yangObj);
+ if (br == null) {
+ return;
+ }
+ try {
+ br.setLogging(DEF_LOGFILE, DEF_LOGLEVEL);
+ } catch (Exception e) {
+ LOG.error(yangObj+" Delete received exception: \""+e+"\"; "
+ +delWarn);
+ }
+ }
+ }
+
+ protected void update(InstanceIdentifier<Logging> iid,
+ Logging oldval, Logging newval) {
+ synchronized(BgpConfigurationManager.this) {
+ BgpRouter br = getClient(yangObj);
+ if (br == null) {
+ return;
+ }
+ try {
+ br.setLogging(newval.getFile(),newval.getLevel());
+ } catch (Exception e) {
+ LOG.error(yangObj+"newval received exception: \""+e+"\"; "
+ +addWarn);
+ }
+ }
+ }
+
+ public void close() {
+ int i;
+ for (i=0 ; i < reactors.length ; i++) {
+ if (reactors[i] == LoggingReactor.class) {
+ break;
+ }
+ }
+ registrations[i].close();
+ }
+ }
+
+ public class NeighborsReactor
+ extends AbstractDataChangeListener<Neighbors>
+ implements AutoCloseable {
+
+ private static final String yangObj = "neighbors ";
+
+ public NeighborsReactor() {
+ super(Neighbors.class);
+ }
+
+ protected synchronized void
+ add(InstanceIdentifier<Neighbors> iid, Neighbors val) {
+ LOG.debug("received add Neighbors config val {}", val.getAddress().getValue());
+ synchronized(BgpConfigurationManager.this) {
+ BgpRouter br = getClient(yangObj);
+ if (br == null) {
+ return;
+ }
+ String peerIp = val.getAddress().getValue();
+ int as = val.getRemoteAs().intValue();
+ try {
+ //itmProvider.buildTunnelsToDCGW(new IpAddress(peerIp.toCharArray()));
+ br.addNeighbor(peerIp, as);
+
+ } catch (Exception e) {
+ LOG.error(yangObj+"Add received exception: \""+e+"\"; "
+ +addWarn);
+ }
+ }
+ }
+
+ protected synchronized void
+ remove(InstanceIdentifier<Neighbors> iid, Neighbors val) {
+ LOG.debug("received remove Neighbors config val {}", val.getAddress().getValue());
+ synchronized(BgpConfigurationManager.this) {
+ BgpRouter br = getClient(yangObj);
+ if (br == null) {
+ return;
+ }
+ String peerIp = val.getAddress().getValue();
+ try {
+ //itmProvider.deleteTunnelsToDCGW(new IpAddress(val.getAddress().getValue().toCharArray()));
+ br.delNeighbor(peerIp);
+ } catch (Exception e) {
+ LOG.error(yangObj+" Delete received exception: \""+e+"\"; "
+ +delWarn);
+ }
+ }
+ }
+
+ protected void update(InstanceIdentifier<Neighbors> iid,
+ Neighbors oldval, Neighbors newval) {
+ //purposefully nothing to do.
+ }
+
+ public void close() {
+ int i;
+ for (i=0 ; i < reactors.length ; i++) {
+ if (reactors[i] == NeighborsReactor.class) {
+ break;
+ }
+ }
+ registrations[i].close();
+ }
+ }
+
+ public class EbgpMultihopReactor
+ extends AbstractDataChangeListener<EbgpMultihop>
+ implements AutoCloseable {
+
+ private static final String yangObj = "ebgp-multihop ";
+
+ public EbgpMultihopReactor() {
+ super(EbgpMultihop.class);
+ }
+
+ protected synchronized void
+ add(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
+ LOG.debug("received add EbgpMultihop config val {}", val.getPeerIp().getValue());
+ synchronized(BgpConfigurationManager.this) {
+ BgpRouter br = getClient(yangObj);
+ if (br == null) {
+ return;
+ }
+ String peerIp = val.getPeerIp().getValue();
+ try {
+ br.addEbgpMultihop(peerIp, val.getNhops().intValue());
+ } catch (Exception e) {
+ LOG.error(yangObj+"Add received exception: \""+e+"\"; "
+ +addWarn);
+ }
+ }
+ }
+
+ protected synchronized void
+ remove(InstanceIdentifier<EbgpMultihop> iid, EbgpMultihop val) {
+ LOG.debug("received remove EbgpMultihop config val {}", val.getPeerIp().getValue());
+ synchronized(BgpConfigurationManager.this) {
+ BgpRouter br = getClient(yangObj);
+ if (br == null) {
+ return;
+ }
+ String peerIp = val.getPeerIp().getValue();
+ try {
+ br.delEbgpMultihop(peerIp);
+ } catch (Exception e) {
+ LOG.error(yangObj+" Delete received exception: \""+e+"\"; "
+ +delWarn);
+ }
+ }
+ }
+
+ protected void update(InstanceIdentifier<EbgpMultihop> iid,
+ EbgpMultihop oldval, EbgpMultihop newval) {
+ LOG.error(yangObj + updWarn);
+ }
+
+ public void close() {
+ int i;
+ for (i=0 ; i < reactors.length ; i++) {
+ if (reactors[i] == EbgpMultihopReactor.class) {
+ break;
+ }
+ }
+ registrations[i].close();
+ }
+ }
+
+ public class UpdateSourceReactor
+ extends AbstractDataChangeListener<UpdateSource>
+ implements AutoCloseable {
+
+ private static final String yangObj = "update-source ";
+
+ public UpdateSourceReactor() {
+ super(UpdateSource.class);
+ }
+
+ protected synchronized void
+ add(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
+ LOG.debug("received add UpdateSource config val {}", val.getSourceIp().getValue());
+ synchronized(BgpConfigurationManager.this) {
+ BgpRouter br = getClient(yangObj);
+ if (br == null) {
+ return;
+ }
+ String peerIp = val.getPeerIp().getValue();
+ try {
+ br.addUpdateSource(peerIp, val.getSourceIp().getValue());
+ } catch (Exception e) {
+ LOG.error(yangObj+"Add received exception: \""+e+"\"; "
+ +addWarn);
+ }
+ }
+ }
+
+ protected synchronized void
+ remove(InstanceIdentifier<UpdateSource> iid, UpdateSource val) {
+ LOG.debug("received remove UpdateSource config val {}", val.getSourceIp().getValue());
+ synchronized(BgpConfigurationManager.this) {
+ BgpRouter br = getClient(yangObj);
+ if (br == null) {
+ return;
+ }
+ String peerIp = val.getPeerIp().getValue();
+ try {
+ br.delUpdateSource(peerIp);
+ } catch (Exception e) {
+ LOG.error(yangObj+" Delete received exception: \""+e+"\"; "
+ +delWarn);
+ }
+ }
+ }
+
+ protected void update(InstanceIdentifier<UpdateSource> iid,
+ UpdateSource oldval, UpdateSource newval) {
+ LOG.error(yangObj + updWarn);
+ }
+
+ public void close() {
+ int i;
+ for (i=0 ; i < reactors.length ; i++) {
+ if (reactors[i] == UpdateSourceReactor.class) {
+ break;
+ }
+ }
+ registrations[i].close();
+ }
+ }
+
+ public class AddressFamiliesReactor
+ extends AbstractDataChangeListener<AddressFamilies>
+ implements AutoCloseable {
+
+ private static final String yangObj = "address-families ";
+
+ public AddressFamiliesReactor() {
+ super(AddressFamilies.class);
+ }
+
+ protected synchronized void
+ add(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
+ LOG.debug("received add AddressFamilies config val {}", val.getPeerIp().getValue());
+ synchronized(BgpConfigurationManager.this) {
+ BgpRouter br = getClient(yangObj);
+ if (br == null) {
+ return;
+ }
+ String peerIp = val.getPeerIp().getValue();
+ af_afi afi = af_afi.findByValue(val.getAfi().intValue());
+ af_safi safi = af_safi.findByValue(val.getSafi().intValue());
+ try {
+ br.addAddressFamily(peerIp, afi, safi);
+ } catch (Exception e) {
+ LOG.error(yangObj+"Add received exception: \""+e+"\"; "
+ +addWarn);
+ }
+ }
+ }
+
+ protected synchronized void
+ remove(InstanceIdentifier<AddressFamilies> iid, AddressFamilies val) {
+ LOG.debug("received remove AddressFamilies config val {}", val.getPeerIp().getValue());
+ synchronized(BgpConfigurationManager.this) {
+ BgpRouter br = getClient(yangObj);
+ if (br == null) {
+ return;
+ }
+ String peerIp = val.getPeerIp().getValue();
+ af_afi afi = af_afi.findByValue(val.getAfi().intValue());
+ af_safi safi = af_safi.findByValue(val.getSafi().intValue());
+ try {
+ br.delAddressFamily(peerIp, afi, safi);
+ } catch (Exception e) {
+ LOG.error(yangObj+" Delete received exception: \""+e+"\"; "
+ +delWarn);
+ }
+ }
+ }
+
+ protected void update(InstanceIdentifier<AddressFamilies> iid,
+ AddressFamilies oldval, AddressFamilies newval) {
+ LOG.error(yangObj + updWarn);
+ }
+
+ public void close() {
+ int i;
+ for (i=0 ; i < reactors.length ; i++) {
+ if (reactors[i] == AddressFamiliesReactor.class) {
+ break;
+ }
+ }
+ registrations[i].close();
+ }
+ }
+
+ public class NetworksReactor
+ extends AbstractDataChangeListener<Networks>
+ implements AutoCloseable {
+
+ private static final String yangObj = "networks ";
+
+ public NetworksReactor() {
+ super(Networks.class);
+ }
+
+ protected synchronized void
+ add(InstanceIdentifier<Networks> iid, Networks val) {
+ LOG.debug("received add Networks config val {}", val.getPrefixLen());
+ synchronized(BgpConfigurationManager.this) {
+ BgpRouter br = getClient(yangObj);
+ if (br == null) {
+ return;
+ }
+ String rd = val.getRd();
+ String pfxlen = val.getPrefixLen();
+ String nh = val.getNexthop().getValue();
+ Long label = val.getLabel();
+ int lbl = (label == null) ? qbgpConstants.LBL_NO_LABEL
+ : label.intValue();
+ try {
+ br.addPrefix(rd, pfxlen, nh, lbl);
+ } catch (Exception e) {
+ LOG.error(yangObj+"Add received exception: \""+e+"\"; "+addWarn);
+ }
+ }
+ }
+
+ protected synchronized void
+ remove(InstanceIdentifier<Networks> iid, Networks val) {
+ LOG.debug("received remove Networks config val {}", val.getPrefixLen());
+ synchronized(BgpConfigurationManager.this) {
+ BgpRouter br = getClient(yangObj);
+ if (br == null) {
+ return;
+ }
+ String rd = val.getRd();
+ String pfxlen = val.getPrefixLen();
+ Long label = val.getLabel();
+ int lbl = (label == null) ? 0 : label.intValue();
+ if (rd == null && lbl > 0) {
+ //LU prefix is being deleted.
+ rd = Integer.toString(lbl);
+ }
+ try {
+ br.delPrefix(rd, pfxlen);
+ } catch (Exception e) {
+ LOG.error(yangObj+" Delete received exception: \""+e+"\"; "
+ +delWarn);
+ }
+ }
+ }
+
+ protected void update(InstanceIdentifier<Networks> iid,
+ Networks oldval, Networks newval) {
+ LOG.error(yangObj + updWarn);
+ }
+
+ public void close() {
+ int i;
+ for (i=0 ; i < reactors.length ; i++) {
+ if (reactors[i] == NetworksReactor.class) {
+ break;
+ }
+ }
+ registrations[i].close();
+ }
+ }
+
+ public class VrfsReactor
+ extends AbstractDataChangeListener<Vrfs>
+ implements AutoCloseable {
+
+ private static final String yangObj = "vrfs ";
+
+ public VrfsReactor() {
+ super(Vrfs.class);
+ }
+
+ protected synchronized void
+ add(InstanceIdentifier<Vrfs> iid, Vrfs val) {
+ LOG.debug("received add Vrfs config val {}", val.getRd());
+ synchronized(BgpConfigurationManager.this) {
+ BgpRouter br = getClient(yangObj);
+ if (br == null) {
+ return;
+ }
+ try {
+ br.addVrf(val.getRd(), val.getImportRts(),
+ val.getExportRts());
+ } catch (Exception e) {
+ LOG.error(yangObj+"Add received exception: \""+e+"\"; "
+ +addWarn);
+ }
+ }
+ }
+
+ protected synchronized void
+ remove(InstanceIdentifier<Vrfs> iid, Vrfs val) {
+ LOG.debug("received remove Vrfs config val {}", val.getRd());
+ synchronized(BgpConfigurationManager.this) {
+ BgpRouter br = getClient(yangObj);
+ if (br == null) {
+ return;
+ }
+ try {
+ br.delVrf(val.getRd());
+ } catch (Exception e) {
+ LOG.error(yangObj+" Delete received exception: \""+e+"\"; "
+ +delWarn);
+ }
+ }
+ }
+
+ protected void update(InstanceIdentifier<Vrfs> iid,
+ Vrfs oldval, Vrfs newval) {
+ LOG.error(yangObj + updWarn);
+ }
+
+ public void close() {
+ int i;
+ for (i=0 ; i < reactors.length ; i++) {
+ if (reactors[i] == VrfsReactor.class) {
+ break;
+ }
+ }
+ registrations[i].close();
+ }
+ }
+
+ Future lastCleanupJob;
+ AtomicReference<Future> lastCleanupJobReference = new AtomicReference<>();
+
+ AtomicBoolean started = new AtomicBoolean(false);
+ public class BgpReactor
+ extends AbstractDataChangeListener<Bgp>
+ implements AutoCloseable {
+
+ private static final String yangObj = "Bgp ";
+
+ public BgpReactor() {
+ super(Bgp.class);
+ }
+
+ protected synchronized void
+ add(InstanceIdentifier<Bgp> iid, Bgp val) {
+ LOG.debug("received add Bgp config replaying the config");
+ try {
+ initer.await();
+ } catch (Exception e) {
+ }
+ synchronized(BgpConfigurationManager.this) {
+ config = val;
+ if (restarting) {
+ if (isIpAvailable(odlThriftIp)) {
+ bgpRestarted();
+ } else {
+ ipActivationCheckTimer.scheduleAtFixedRate(new TimerTask() {
+ public void run() {
+ if (isIpAvailable(odlThriftIp)) {
+ bgpRestarted();
+ ipActivationCheckTimer.cancel();
+ }
+ }
+ }, 10000L, 10000L);
+ }
+ }
+ }
+ }
+
+ protected synchronized void
+ remove(InstanceIdentifier<Bgp> iid, Bgp val) {
+ LOG.debug("received remove Bgp config");
+ synchronized(BgpConfigurationManager.this) {
+ config = null;
+ }
+ }
+
+ protected void update(InstanceIdentifier<Bgp> iid,
+ Bgp oldval, Bgp newval) {
+ synchronized(BgpConfigurationManager.this) {
+ config = newval;
+ }
+ }
+
+ public void close() {
+ int i;
+ for (i=0 ; i < reactors.length ; i++) {
+ if (reactors[i] == BgpReactor.class) {
+ break;
+ }
+ }
+ registrations[i].close();
+ }
+ }
+
+ public void readOdlThriftIpForBgpCommunication() {
+ File f = new File(CLUSTER_CONF_FILE);
+ if (!f.exists()) {
+ odlThriftIp = "127.0.0.1";
+ return;
+ }
+ BufferedReader br = null;
+ try {
+ br = new BufferedReader(new InputStreamReader(
+ new FileInputStream(f)));
+ String line = br.readLine();
+ while (line != null) {
+ if (line.contains(SDNC_BGP_MIP)) {
+ line = line.trim();
+ odlThriftIp = line.substring(line.lastIndexOf(" ")+1);
+ break;
+ }
+ line = br.readLine();
+ }
+ } catch (Exception e) {
+ } finally {
+ try {br.close();} catch (Exception ignore){}
+ }
+ }
+
+ public boolean isIpAvailable(String odlip) {
+
+ try {
+ if (odlip != null) {
+ if ("127.0.0.1".equals(odlip)) {
+ return true;
+ }
+ Enumeration e = NetworkInterface.getNetworkInterfaces();
+ while(e.hasMoreElements())
+ {
+ NetworkInterface n = (NetworkInterface) e.nextElement();
+ Enumeration ee = n.getInetAddresses();
+ while (ee.hasMoreElements())
+ {
+ InetAddress i = (InetAddress) ee.nextElement();
+ if (odlip.equals(i.getHostAddress())) {
+ return true;
+ };
+ }
+ }
+ }
+ } catch (Exception e) {
+ }
+ return false;
+ }
+
+ public void bgpRestarted() {
+ /*
+ * If there a thread which in the process of stale cleanup, cancel it
+ * and start a new thread (to avoid processing same again).
+ */
+ if (lastCleanupJobReference.get() != null) {
+ lastCleanupJobReference.get().cancel(true);
+ lastCleanupJobReference.set(null);
+ }
+ Runnable task = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ long startTime = System.currentTimeMillis();
+ LOG.error("started creating stale fib map ");
+ createStaleFibMap();
+ long endTime = System.currentTimeMillis();
+ LOG.error("took {} msecs for stale fib map creation ", endTime - startTime);
+ LOG.error("started bgp config replay ");
+ startTime = endTime;
+ replay();
+ endTime = System.currentTimeMillis();
+ LOG.error("took {} msecs for bgp replay ", endTime - startTime);
+ long route_sync_time = BGP_RESTART_ROUTE_SYNC_SEC;
+ try {
+ route_sync_time = bgpManager.getConfig().getGracefulRestart().getStalepathTime();
+ } catch (Exception e) {
+ LOG.error("BGP config/Stale-path time is not set");
+ }
+ Thread.sleep(route_sync_time * 1000L);
+ new RouteCleanup().call();
+
+ } catch (Exception eCancel) {
+ LOG.error("Stale Cleanup Task Cancelled", eCancel);
+ }
+ }
+ };
+ lastCleanupJob = executor.submit(task);
+ lastCleanupJobReference.set(lastCleanupJob);
+ }
+
+ private static void doRouteSync() {
+ BgpSyncHandle bsh = BgpSyncHandle.getInstance();
+ LOG.debug("Starting BGP route sync");
+ try {
+ bgpRouter.initRibSync(bsh);
+ } catch (Exception e) {
+ LOG.error("Route sync aborted, exception when initialzing: "+e);
+ return;
+ }
+ while (bsh.getState() != bsh.DONE) {
+ Routes routes = null;
+ try {
+ routes = bgpRouter.doRibSync(bsh);
+ } catch (Exception e) {
+ LOG.error("Route sync aborted, exception when syncing: "+e);
+ return;
+ }
+ Iterator<Update> updates = routes.getUpdatesIterator();
+ while (updates.hasNext()) {
+ Update u = updates.next();
+ Map<String, Map<String, String>> stale_fib_rd_map = BgpConfigurationManager.getStaledFibEntriesMap();
+ String rd = u.getRd();
+ String nexthop = u.getNexthop();
+ int label = u.getLabel();
+ String prefix = u.getPrefix();
+ int plen = u.getPrefixlen();
+ onUpdatePushRoute(rd, prefix, plen, nexthop, label);
+ }
+ }
+ try {
+ LOG.debug("Ending BGP route-sync");
+ bgpRouter.endRibSync(bsh);
+ } catch (Exception e) {
+ }
+ }
+
+ /* onUpdatePushRoute
+ * Get Stale fib map, and compare current route/fib entry.
+ * - Entry compare shall include NextHop, Label.
+ * - If entry matches: delete from STALE Map. NO Change to FIB Config DS.
+ * - If entry nor found, add to FIB Config DS.
+ * - If entry found, but either Label/NextHop doesnt match.
+ * - Update FIB Config DS with modified values.
+ * - delete from Stale Map.
+ */
+ public static void onUpdatePushRoute(String rd, String prefix, int plen,
+ String nexthop, int label) {
+ Map<String, Map<String, String>> stale_fib_rd_map = BgpConfigurationManager.getStaledFibEntriesMap();
+ boolean addroute = false;
+ if (!stale_fib_rd_map.isEmpty()) {
+ // restart Scenario, as MAP is not empty.
+ Map<String, String> map = stale_fib_rd_map.get(rd);
+ if (map !=null) {
+ String nexthoplabel = map.get(prefix + "/" + plen);
+ if (null == nexthoplabel) {
+ // New Entry, which happend to be added during restart.
+ addroute = true;
+ } else {
+ map.remove(prefix + "/" + plen);
+ if (isRouteModified(nexthop, label, nexthoplabel)) {
+ LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix,
+ plen, nexthop, label);
+ // Existing entry, where in Nexthop/Label got modified during restart
+ addroute = true;
+ }
+ }
+ }
+ } else {
+ LOG.debug("Route add ** {} ** {}/{} ** {} ** {} ", rd, prefix,
+ plen, nexthop, label);
+ addroute = true;
+ }
+ if (addroute) {
+ fib.addFibEntryToDS(rd, prefix + "/" + plen,
+ nexthop, label);
+ }
+ }
+
+ private static boolean isRouteModified(String nexthop, int label, String nexthoplabel) {
+ return !nexthoplabel.isEmpty() && !nexthoplabel.equals(nexthop+"/"+label);
+ }
+
+ static private void replayNbrConfig(List<Neighbors> n, BgpRouter br) {
+ for (Neighbors nbr : n) {
+ try {
+ br.addNeighbor(nbr.getAddress().getValue(),
+ nbr.getRemoteAs().intValue());
+ //itmProvider.buildTunnelsToDCGW(new IpAddress(nbr.getAddress().getValue().toCharArray()));
+ } catch (Exception e) {
+ LOG.error("Replay:addNbr() received exception: \""+e+"\"");
+ continue;
+ }
+ EbgpMultihop en = nbr.getEbgpMultihop();
+ if (en != null) {
+ try {
+ br.addEbgpMultihop(en.getPeerIp().getValue(),
+ en.getNhops().intValue());
+ } catch (Exception e) {
+ LOG.error("Replay:addEBgp() received exception: \""+e+"\"");
+ }
+ }
+ UpdateSource us = nbr.getUpdateSource();
+ if (us != null) {
+ try {
+ br.addUpdateSource(us.getPeerIp().getValue(),
+ us.getSourceIp().getValue());
+ } catch (Exception e) {
+ LOG.error("Replay:addUS() received exception: \""+e+"\"");
+ }
+ }
+ List<AddressFamilies> afs = nbr.getAddressFamilies();
+ if (afs != null) {
+ for (AddressFamilies af : afs) {
+ af_afi afi = af_afi.findByValue(af.getAfi().intValue());
+ af_safi safi = af_safi.findByValue(af.getSafi().intValue());
+ try {
+ br.addAddressFamily(af.getPeerIp().getValue(), afi, safi);
+ } catch (Exception e) {
+ LOG.error("Replay:addAf() received exception: \""+e+"\"");
+ }
+ }
+ }
+ }
+ }
+
+ public static String getConfigHost() {
+ if (config == null) {
+ return cHostStartup;
+ }
+ ConfigServer ts = config.getConfigServer();
+ return (ts == null ? cHostStartup : ts.getHost().getValue());
+ }
+
+ public static int getConfigPort() {
+ if (config == null) {
+ return Integer.parseInt(cPortStartup);
+ }
+ ConfigServer ts = config.getConfigServer();
+ return (ts == null ? Integer.parseInt(cPortStartup) :
+ ts.getPort().intValue());
+ }
+
+ public static synchronized void replay() {
+ String host = getConfigHost();
+ int port = getConfigPort();
+ boolean res = bgpRouter.connect(host, port);
+ if (!res) {
+ String msg = "Cannot connect to BGP config server at "+host+":"+port;
+ if (config != null) {
+ msg += "; Configuration Replay aborted";
+ }
+ LOG.error(msg);
+ return;
+ }
+ if (config == null) {
+ return;
+ }
+ BgpRouter br = bgpRouter;
+ AsId a = config.getAsId();
+ if (a == null) {
+ return;
+ }
+ int asNum = a.getLocalAs().intValue();
+ Ipv4Address routerId = a.getRouterId();
+ Long spt = a.getStalepathTime();
+ Boolean afb = a.isAnnounceFbit();
+ String rid = (routerId == null) ? "" : routerId.getValue();
+ int stalepathTime = (spt == null) ? 90 : spt.intValue();
+ boolean announceFbit = (afb == null) ? false : afb.booleanValue();
+ try {
+ br.startBgp(asNum, rid, stalepathTime, announceFbit);
+ } catch (BgpRouterException bre) {
+ if (bre.getErrorCode() == BgpRouterException.BGP_ERR_ACTIVE) {
+ doRouteSync();
+ } else {
+ LOG.error("Replay: startBgp() received exception: \""
+ +bre+"\"; "+addWarn);
+ }
+ } catch (Exception e) {
+ //not unusual. We may have restarted & BGP is already on
+ LOG.error("Replay:startBgp() received exception: \""+e+"\"");
+ }
+
+ if (bgpManager.getBgpCounters() == null) {
+ bgpManager.startBgpCountersTask();
+ }
+
+ Logging l = config.getLogging();
+ if (l != null) {
+ try {
+ br.setLogging(l.getFile(), l.getLevel());
+ } catch (Exception e) {
+ LOG.error("Replay:setLogging() received exception: \""+e+"\"");
+ }
+ }
+
+ GracefulRestart g = config.getGracefulRestart();
+ if (g != null) {
+ try {
+ br.addGracefulRestart(g.getStalepathTime().intValue());
+ } catch (Exception e) {
+ LOG.error("Replay:addGr() received exception: \""+e+"\"");
+ }
+ }
+
+ List<Neighbors> n = config.getNeighbors();
+ if (n != null) {
+ replayNbrConfig(n, br);
+ }
+
+ List<Vrfs> v = config.getVrfs();
+ if (v != null) {
+ for (Vrfs vrf : v) {
+ try {
+ br.addVrf(vrf.getRd(), vrf.getImportRts(),
+ vrf.getExportRts());
+ } catch (Exception e) {
+ LOG.error("Replay:addVrf() received exception: \""+e+"\"");
+ }
+ }
+ }
+
+ List<Networks> ln = config.getNetworks();
+ if (ln != null) {
+ for (Networks net : ln) {
+ String rd = net.getRd();
+ String pfxlen = net.getPrefixLen();
+ String nh = net.getNexthop().getValue();
+ Long label = net.getLabel();
+ int lbl = (label == null) ? 0 : label.intValue();
+ if (rd == null && lbl > 0) {
+ //LU prefix is being deleted.
+ rd = Integer.toString(lbl);
+ }
+ try {
+ br.addPrefix(rd, pfxlen, nh, lbl);
+ } catch (Exception e) {
+ LOG.error("Replay:addPfx() received exception: \""+e+"\"");
+ }
+ }
+ }
+ }
+
+ private <T extends DataObject> void update(InstanceIdentifier<T> iid, T dto) {
+ BgpUtil.update(broker, LogicalDatastoreType.CONFIGURATION, iid, dto);
+ }
+
+ private <T extends DataObject> void asyncWrite(InstanceIdentifier<T> iid, T dto) {
+ BgpUtil.write(broker,LogicalDatastoreType.CONFIGURATION,iid,dto);
+ }
+
+ private <T extends DataObject> void delete(InstanceIdentifier<T> iid) {
+ BgpUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, iid);
+ }
+
+ public synchronized void
+ startConfig(String bgpHost, int thriftPort) {
+ InstanceIdentifier.InstanceIdentifierBuilder<ConfigServer> iib =
+ InstanceIdentifier.builder(Bgp.class).child(ConfigServer.class);
+ InstanceIdentifier<ConfigServer> iid = iib.build();
+ Ipv4Address ipAddr = new Ipv4Address(bgpHost);
+ ConfigServer dto = new ConfigServerBuilder().setHost(ipAddr)
+ .setPort((long) thriftPort).build();
+ update(iid, dto);
+ }
+
+ public synchronized void
+ startBgp(int as, String routerId, int spt, boolean fbit) {
+ Long localAs = (long) as;
+ Ipv4Address rid = (routerId == null) ?
+ null : new Ipv4Address(routerId);
+ Long staleTime = (long) spt;
+ InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
+ InstanceIdentifier.builder(Bgp.class).child(AsId.class);
+ InstanceIdentifier<AsId> iid = iib.build();
+ AsId dto = new AsIdBuilder().setLocalAs(localAs)
+ .setRouterId(rid)
+ .setStalepathTime(staleTime)
+ .setAnnounceFbit(fbit).build();
+ update(iid, dto);
+ }
+
+ public synchronized void
+ addLogging(String fileName, String logLevel) {
+ InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
+ InstanceIdentifier.builder(Bgp.class).child(Logging.class);
+ InstanceIdentifier<Logging> iid = iib.build();
+ Logging dto = new LoggingBuilder().setFile(fileName)
+ .setLevel(logLevel).build();
+ update(iid, dto);
+ }
+
+ public synchronized void
+ addGracefulRestart(int staleTime) {
+ InstanceIdentifier.InstanceIdentifierBuilder<GracefulRestart> iib =
+ InstanceIdentifier.builder(Bgp.class).child(GracefulRestart.class);
+ InstanceIdentifier<GracefulRestart> iid = iib.build();
+ GracefulRestart dto = new GracefulRestartBuilder()
+ .setStalepathTime((long)staleTime).build();
+ update(iid, dto);
+ }
+
+ public synchronized void
+ addNeighbor(String nbrIp, int remoteAs) {
+ Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
+ Long rAs = (long) remoteAs;
+ InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib =
+ InstanceIdentifier.builder(Bgp.class)
+ .child(Neighbors.class, new NeighborsKey(nbrAddr));
+ InstanceIdentifier<Neighbors> iid = iib.build();
+ Neighbors dto = new NeighborsBuilder().setAddress(nbrAddr)
+ .setRemoteAs(rAs).build();
+ update(iid, dto);
+ }
+
+ public synchronized void
+ addUpdateSource(String nbrIp, String srcIp) {
+ Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
+ Ipv4Address srcAddr = new Ipv4Address(srcIp);
+ InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib =
+ InstanceIdentifier.builder(Bgp.class)
+ .child(Neighbors.class, new NeighborsKey(nbrAddr))
+ .child(UpdateSource.class);
+ InstanceIdentifier<UpdateSource> iid = iib.build();
+ UpdateSource dto = new UpdateSourceBuilder().setPeerIp(nbrAddr)
+ .setSourceIp(srcAddr).build();
+ update(iid, dto);
+ }
+
+ public synchronized void
+ addEbgpMultihop(String nbrIp, int nHops) {
+ Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
+ InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib =
+ InstanceIdentifier.builder(Bgp.class)
+ .child(Neighbors.class, new NeighborsKey(nbrAddr))
+ .child(EbgpMultihop.class);
+ InstanceIdentifier<EbgpMultihop> iid = iib.build();
+ EbgpMultihop dto = new EbgpMultihopBuilder().setPeerIp(nbrAddr)
+ .setNhops((long)nHops).build();
+ update(iid, dto);
+ }
+
+ public synchronized void
+ addAddressFamily(String nbrIp, int afi, int safi) {
+ Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
+ Long a = (long) afi;
+ Long sa = (long) safi;
+ InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib =
+ InstanceIdentifier.builder(Bgp.class)
+ .child(Neighbors.class, new NeighborsKey(nbrAddr))
+ .child(AddressFamilies.class, new AddressFamiliesKey(a, sa));
+ InstanceIdentifier<AddressFamilies> iid = iib.build();
+ AddressFamilies dto = new AddressFamiliesBuilder().setPeerIp(nbrAddr)
+ .setAfi(a).setSafi(sa).build();
+ update(iid, dto);
+ }
+
+ public synchronized void
+ addPrefix(String rd, String pfx, String nh, int lbl) {
+ Ipv4Address nexthop = new Ipv4Address(nh);
+ Long label = (long) lbl;
+ InstanceIdentifier.InstanceIdentifierBuilder<Networks> iib =
+ InstanceIdentifier.builder(Bgp.class)
+ .child(Networks.class, new NetworksKey(pfx, rd));
+ InstanceIdentifier<Networks> iid = iib.build();
+ Networks dto = new NetworksBuilder().setRd(rd)
+ .setPrefixLen(pfx)
+ .setNexthop(nexthop)
+ .setLabel(label).build();
+ update(iid, dto);
+ }
+
+ public synchronized void
+ addVrf(String rd, List<String> irts, List<String> erts) {
+ InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib =
+ InstanceIdentifier.builder(Bgp.class)
+ .child(Vrfs.class, new VrfsKey(rd));
+ InstanceIdentifier<Vrfs> iid = iib.build();
+ Vrfs dto = new VrfsBuilder().setRd(rd)
+ .setImportRts(irts)
+ .setExportRts(erts).build();
+
+ asyncWrite(iid, dto);
+ }
+
+ public synchronized void stopConfig() {
+ InstanceIdentifier.InstanceIdentifierBuilder<ConfigServer> iib =
+ InstanceIdentifier.builder(Bgp.class).child(ConfigServer.class);
+ InstanceIdentifier<ConfigServer> iid = iib.build();
+ delete(iid);
+ }
+
+ public synchronized void stopBgp() {
+ InstanceIdentifier.InstanceIdentifierBuilder<AsId> iib =
+ InstanceIdentifier.builder(Bgp.class).child(AsId.class);
+ InstanceIdentifier<AsId> iid = iib.build();
+ delete(iid);
+ }
+
+ public synchronized void delLogging() {
+ InstanceIdentifier.InstanceIdentifierBuilder<Logging> iib =
+ InstanceIdentifier.builder(Bgp.class).child(Logging.class);
+ InstanceIdentifier<Logging> iid = iib.build();
+ delete(iid);
+ }
+
+ public synchronized void delGracefulRestart() {
+ InstanceIdentifier.InstanceIdentifierBuilder<GracefulRestart> iib =
+ InstanceIdentifier.builder(Bgp.class)
+ .child(GracefulRestart.class);
+ InstanceIdentifier<GracefulRestart> iid = iib.build();
+ delete(iid);
+ }
+
+ public synchronized void delNeighbor(String nbrIp) {
+ Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
+ InstanceIdentifier.InstanceIdentifierBuilder<Neighbors> iib =
+ InstanceIdentifier.builder(Bgp.class)
+ .child(Neighbors.class, new NeighborsKey(nbrAddr));
+ InstanceIdentifier<Neighbors> iid = iib.build();
+ delete(iid);
+ }
+
+ public synchronized void delUpdateSource(String nbrIp) {
+ Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
+ InstanceIdentifier.InstanceIdentifierBuilder<UpdateSource> iib =
+ InstanceIdentifier.builder(Bgp.class)
+ .child(Neighbors.class, new NeighborsKey(nbrAddr))
+ .child(UpdateSource.class);
+ InstanceIdentifier<UpdateSource> iid = iib.build();
+ delete(iid);
+ }
+
+ public synchronized void delEbgpMultihop(String nbrIp) {
+ Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
+ InstanceIdentifier.InstanceIdentifierBuilder<EbgpMultihop> iib =
+ InstanceIdentifier.builder(Bgp.class)
+ .child(Neighbors.class, new NeighborsKey(nbrAddr))
+ .child(EbgpMultihop.class);
+ InstanceIdentifier<EbgpMultihop> iid = iib.build();
+ delete(iid);
+ }
+
+ public synchronized void
+ delAddressFamily(String nbrIp, int afi, int safi) {
+ Ipv4Address nbrAddr = new Ipv4Address(nbrIp);
+ Long a = (long) afi;
+ Long sa = (long) safi;
+ InstanceIdentifier.InstanceIdentifierBuilder<AddressFamilies> iib =
+ InstanceIdentifier.builder(Bgp.class)
+ .child(Neighbors.class, new NeighborsKey(nbrAddr))
+ .child(AddressFamilies.class, new AddressFamiliesKey(a, sa));
+ InstanceIdentifier<AddressFamilies> iid = iib.build();
+ delete(iid);
+ }
+
+ public synchronized void delPrefix(String rd, String pfx) {
+ InstanceIdentifier.InstanceIdentifierBuilder<Networks> iib =
+ InstanceIdentifier.builder(Bgp.class)
+ .child(Networks.class, new NetworksKey(pfx, rd));
+ InstanceIdentifier<Networks> iid = iib.build();
+ delete(iid);
+ }
+
+ public synchronized void delVrf(String rd) {
+ InstanceIdentifier.InstanceIdentifierBuilder<Vrfs> iib =
+ InstanceIdentifier.builder(Bgp.class)
+ .child(Vrfs.class, new VrfsKey(rd));
+ InstanceIdentifier<Vrfs> iid = iib.build();
+ delete(iid);
+ }
+
+ static ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
+ /*
+ * Remove Stale Marked Routes after timer expiry.
+ */
+ class RouteCleanup implements Callable<Integer> {
+
+ public Integer call () {
+ int totalCleared = 0;
+ try {
+ if (staledFibEntriesMap.isEmpty()) {
+ LOG.info("BGP: RouteCleanup timertask tirggered but STALED FIB MAP is EMPTY");
+ } else {
+ for (String rd : staledFibEntriesMap.keySet()) {
+ if (Thread.interrupted()) {
+ return 0;
+ }
+ Map<String, String> map = staledFibEntriesMap.get(rd);
+ if (map != null) {
+ for (String prefix : map.keySet()) {
+ if (Thread.interrupted()) {
+ return 0;
+ }
+ try {
+ totalCleared++;
+ bgpManager.deletePrefix(rd, prefix);
+ } catch (Exception e) {
+ LOG.error("BGP: RouteCleanup deletePrefix failed rd:{}, prefix{}" + rd.toString() + prefix);
+ }
+ }
+ }
+ }
+ }
+ } catch(Exception e) {
+ LOG.error("Cleanup Thread Got interrupted, Failed to cleanup stale routes ", e);
+ } finally {
+ staledFibEntriesMap.clear();
+ }
+ LOG.error("cleared {} stale routes after bgp restart", totalCleared);
+ return 0;
+ }
+ }
+
+ /*
+ * BGP restart scenario, ODL-BGP manager was/is running.
+ * On re-sync notification, Get a copy of FIB database.
+ */
+ public static void createStaleFibMap() {
+ int totalStaledCount = 0;
+ try {
+ staledFibEntriesMap.clear();
+ InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
+ DataBroker db = BgpUtil.getBroker();
+ if (db == null) {
+ LOG.error("Couldn't find BgpUtil broker while creating createStaleFibMap");
+ return;
+ }
+
+ Optional<FibEntries> fibEntries = BgpUtil.read(BgpUtil.getBroker(),
+ LogicalDatastoreType.CONFIGURATION, id);
+ if (fibEntries.isPresent()) {
+ List<VrfTables> stale_vrfTables = fibEntries.get().getVrfTables();
+ for (VrfTables vrfTable : stale_vrfTables) {
+ Map<String, String> stale_fib_ent_map = new HashMap<>();
+ for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
+ if (Thread.interrupted()) {
+ break;
+ }
+ totalStaledCount++;
+ //Create MAP from stale_vrfTables.
+ stale_fib_ent_map.put(vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddress() + "/" + vrfEntry.getLabel());
+ }
+ staledFibEntriesMap.put(vrfTable.getRouteDistinguisher(), stale_fib_ent_map);
+ }
+ } else {
+ LOG.error("createStaleFibMap:: FIBentries.class is not present");
+ }
+ } catch (Exception e) {
+ LOG.error("createStaleFibMap:: erorr ", e);
+ }
+ LOG.error("created {} staled entries ", totalStaledCount);
+ }
+
+ //map<rd, map<prefix/len, nexthop/label>>
+ public static Map<String, Map<String, String>> getStaledFibEntriesMap() {
+ return staledFibEntriesMap;
+ }
+
+
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.bgpmanager;
+
+import java.lang.management.ManagementFactory;
+import java.util.*;
+import java.util.concurrent.CountDownLatch;
+import javax.management.*;
+import org.apache.thrift.TException;
+import org.opendaylight.bgpmanager.api.IBgpManager;
+import org.opendaylight.bgpmanager.commands.Commands;
+import org.opendaylight.bgpmanager.oam.*;
+import org.opendaylight.bgpmanager.thrift.gen.af_afi;
+import org.opendaylight.bgpmanager.thrift.gen.af_safi;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+//import org.opendaylight.vpnservice.itm.api.IITMProvider;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.Bgp;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.Neighbors;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BgpManager implements BindingAwareProvider, AutoCloseable, IBgpManager {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(BgpManager.class);
+ private BgpConfigurationManager bcm;
+ private FibDSWriter fibDSWriter;
+ //private IITMProvider itmProvider;
+ private DataBroker dataBroker;
+ private BgpAlarmBroadcaster qbgpAlarmProducer = null;
+ private MBeanServer qbgpAlarmServer = null;
+ private NotificationFilter qbgpAlarmFilter = null;
+ final static int DEFAULT_STALEPATH_TIME = 210;
+ final static boolean DEFAULT_FBIT = true;
+
+ public BgpCounters bgpCounters;
+ public Timer bgpCountersTimer;
+
+ @Override
+ public void onSessionInitiated(ProviderContext session) {
+ try {
+ dataBroker = session.getSALService(DataBroker.class);
+ fibDSWriter = new FibDSWriter(dataBroker);
+ BgpUtil.setBroker(dataBroker);
+ bcm = new BgpConfigurationManager(this);
+ Commands commands = new Commands(this);
+ ConfigureBgpCli.setBgpManager(this);
+ LOGGER.info("BgpManager started");
+ } catch (Exception e) {
+ LOGGER.error("Failed to start BgpManager: "+e);
+ }
+
+ // Set up the Infra for Posting BGP Alarms as JMX notifications.
+ try {
+ qbgpAlarmProducer = new BgpAlarmBroadcaster();
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ ObjectName alarmObj = new ObjectName("SDNC.FM:name=BgpAlarmObj");
+ mbs.registerMBean(qbgpAlarmProducer, alarmObj);
+ } catch (JMException e) {
+ LOGGER.error("Adding a NotificationBroadcaster failed." + e.toString());
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ bcm.close();
+ LOGGER.info("BgpManager Closed");
+ }
+
+ /*public void setITMProvider(IITMProvider itmProvider) {
+ this.itmProvider = itmProvider;
+ }
+
+ public IITMProvider getItmProvider() { return this.itmProvider; } */
+
+ public Bgp getConfig() {
+ return bcm.get();
+ }
+
+ public void configureGR(int stalepathTime) throws TException {
+ bcm.addGracefulRestart(stalepathTime);
+ }
+
+ public void delGracefulRestart() throws Exception {
+ bcm.delGracefulRestart();
+ }
+
+ public void addNeighbor(String ipAddress, long asNum) throws TException {
+ bcm.addNeighbor(ipAddress, (int) asNum);
+ }
+
+ public void addEbgpMultihop(String ipAddress, int nhops) throws TException {
+ bcm.addEbgpMultihop(ipAddress, nhops);
+ }
+
+ public void addUpdateSource(String ipAddress, String srcIp) throws TException {
+ bcm.addUpdateSource(ipAddress, srcIp);
+ }
+
+ public void addAddressFamily(String ipAddress, af_afi afi, af_safi safi) throws TException {
+ bcm.addAddressFamily(ipAddress, afi.getValue(), safi.getValue());
+ }
+
+ public void deleteNeighbor(String ipAddress) throws TException {
+ bcm.delNeighbor(ipAddress);
+ }
+
+ @Override
+ public void addVrf(String rd, Collection<String> importRts, Collection<String> exportRts) throws Exception {
+ bcm.addVrf(rd, new ArrayList<String>(importRts),
+ new ArrayList<String>(exportRts));
+ }
+
+ @Override
+ public void deleteVrf(String rd) throws Exception {
+ bcm.delVrf(rd);
+ }
+
+ @Override
+ public void addPrefix(String rd, String prefix, String nextHop, int vpnLabel) throws Exception {
+ fibDSWriter.addFibEntryToDS(rd, prefix, nextHop, vpnLabel);
+ bcm.addPrefix(rd, prefix, nextHop, vpnLabel);
+ }
+
+ @Override
+ public void deletePrefix(String rd, String prefix) throws Exception {
+ fibDSWriter.removeFibEntryFromDS(rd, prefix);
+ bcm.delPrefix(rd, prefix);
+ }
+
+ @Override
+ public void advertisePrefix(String rd, String prefix, String nextHop, int vpnLabel) throws Exception {
+ bcm.addPrefix(rd, prefix, nextHop, vpnLabel);
+ }
+
+ @Override
+ public void withdrawPrefix(String rd, String prefix) throws Exception {
+ bcm.delPrefix(rd, prefix);
+ }
+
+ public void setQbgpLog(String fileName, String debugLevel) throws Exception {
+ bcm.addLogging(fileName, debugLevel);
+ }
+
+ public void delLogging() throws Exception {
+ bcm.delLogging();
+ }
+
+ public void startBgp(int asn, String routerId, int spt, boolean fbit) {
+ bcm.startBgp(asn, routerId, spt, fbit);
+ }
+
+ public void stopBgp() {
+ bcm.stopBgp();
+ }
+
+ public void startConfig(String host, int port) {
+ bcm.startConfig(host, port);
+ }
+
+ public void stopConfig() {
+ bcm.stopConfig();
+ }
+
+ @Override
+ public String getDCGwIP() {
+ Bgp conf = getConfig();
+ if (conf == null) {
+ return null;
+ }
+ List<Neighbors> nbrs = conf.getNeighbors();
+ if (nbrs == null) {
+ return null;
+ }
+ return nbrs.get(0).getAddress().getValue();
+ }
+
+ public MBeanServer getBgpAlarmServer() {
+ return qbgpAlarmServer;
+ }
+
+ public synchronized void sendNotificationEvent(String pfx, int code, int subcode) {
+ BgpAlarmErrorCodes errorSubCode;
+ if (code != BgpConstants.BGP_NOTIFY_CEASE_CODE) {
+ // CEASE Notifications alone have to be reported to the CBA.
+ // Silently return here. No need to log because tons
+ // of non-alarm notifications will be sent to the SDNc.
+ return;
+ }
+ errorSubCode = BgpAlarmErrorCodes.checkErrorSubcode(subcode);
+ if (errorSubCode == BgpAlarmErrorCodes.ERROR_IGNORE) {
+ // Need to report only those subcodes, defined in
+ // BgpAlarmErrorCodes enum class.
+ return;
+ }
+ String alarmString = "";
+ alarmString = "Alarm (" + code + "," + subcode + ") from neighbor " + pfx;
+ qbgpAlarmProducer.sendBgpAlarmInfo(pfx, code, subcode);
+ }
+
+ public Timer getBgpCountersTimer() {
+ return bgpCountersTimer;
+ }
+
+ public BgpCounters getBgpCounters() {
+ return bgpCounters;
+ }
+
+ public void setBgpCountersTimer (Timer t) {
+ bgpCountersTimer = t;
+ }
+
+ public void startBgpCountersTask() {
+ if (getBgpCounters() == null) {
+
+ try {
+ bgpCounters = new BgpCounters();
+ setBgpCountersTimer(new Timer(true));
+ getBgpCountersTimer().scheduleAtFixedRate(bgpCounters, 0, 120 * 1000);
+
+
+ LOGGER.info("Bgp Counters task scheduled for every two minutes.");
+ } catch (Exception e) {
+ System.out.println("Could not start the timertask for Bgp Counters.");
+ e.printStackTrace();
+ }
+
+ try {
+ setQbgpLog(BgpConstants.BGP_DEF_LOG_FILE, BgpConstants.BGP_DEF_LOG_LEVEL);
+ } catch (Exception e) {
+ System.out.println("Could not set the default options for logging");
+ }
+ }
+ }
+
+ public void stopBgpCountersTask() {
+ Timer t = getBgpCountersTimer();
+ if (getBgpCounters() != null) {
+ t.cancel();
+ setBgpCountersTimer(null);
+ bgpCounters = null;
+ }
+ }
+
+ public FibDSWriter getFibWriter() {
+ return fibDSWriter;
+ }
+
+ public DataBroker getBroker() {
+ return dataBroker;
+ }
+
+ public String getConfigHost() {
+ return bcm.getConfigHost();
+ }
+
+ public int getConfigPort() {
+ return bcm.getConfigPort();
+ }
+
+ public void bgpRestarted() {
+ bcm.bgpRestarted();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager;
+
+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.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Created by emhamla on 8/31/2015.
+ */
+public class BgpUtil {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BgpUtil.class);
+ private static DataBroker dataBroker;
+
+ static <T extends DataObject> void update(DataBroker broker, LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.merge(datastoreType, path, data, true);
+ tx.submit();
+ }
+
+ public static <T extends DataObject> void write(DataBroker broker, LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.put(datastoreType, path, data, true);
+ tx.submit();
+ }
+
+ static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.delete(datastoreType, path);
+ tx.submit();
+ }
+
+ 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 void setBroker(DataBroker broker) {
+ BgpUtil.dataBroker = broker;
+ }
+
+ public static DataBroker getBroker() {
+ return dataBroker;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Future;
+
+import org.apache.karaf.shell.commands.*;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.bgpmanager.thrift.gen.af_afi;
+import org.opendaylight.bgpmanager.thrift.gen.af_safi;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.*;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.*;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.*;
+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.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.util.*;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
+@Command(scope = "odl", name = "configure-bgp", description = "")
+public class ConfigureBgpCli extends OsgiCommandSupport {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ConfigureBgpCli.class);
+
+ private static BgpManager bgpManager;
+
+ public static void setBgpManager(BgpManager mgr) {
+ bgpManager = mgr;
+ }
+
+ @Option(name = "-op", aliases = {"--operation","--op"}, description = "[start-bgp-server, stop-bgp-server, add-neighbor, delete-neighbor, graceful-restart, enable-log ]",
+ required = false, multiValued = false)
+ String op;
+
+ //exec configure-bgp add-neighbor --ip <neighbor-ip> --as-num <as-num> --address-family <af> --use-source-ip <sip> --ebgp-multihops <em> --next-hop <nh>
+
+ @Option(name = "--as-num", description = "as number of the bgp neighbor", required = false, multiValued = false)
+ String asNumber = null;
+
+ @Option(name = "--ip", description = "ip of the bgp neighbor", required = false, multiValued = false)
+ String ip = null;
+
+ @Option(name = "--address-family", description = "address family of the bgp neighbor SAFI_IPV4_LABELED_UNICAST|SAFI_MPLS_VPN",
+ required = false, multiValued = false)
+ String addressFamily = null;
+
+ @Option(name = "--use-source-ip", description = "source ip to be used for neighborship connection establishment",
+ required = false, multiValued = false)
+ String sourceIp = null;
+
+ @Option(name = "--ebgp-multihops", description = "ebgp multihops of the bgp neighbor",
+ required = false, multiValued = false)
+ String ebgpMultihops = null;
+
+ @Option(name = "--router-id", description = "router id of the bgp instance",
+ required = false, multiValued = false)
+ String routerId = null;
+
+ @Option(name = "--stalepath-time", description = "the time delay after bgp restart stalepaths are cleaned",
+ required = false, multiValued = false)
+ String stalePathTime = null;
+
+ @Option(name = "--log-file-path", description = "bgp log file path",
+ required = false, multiValued = false)
+ String logFile = null;
+
+ @Option(name = "--log-level", description = "log level emergencies,alerts,critical,errors,warnings,notifications,informational,debugging",
+ required = false, multiValued = false)
+ String logLevel = null;
+
+ enum LogLevels {
+ emergencies,alerts,critical,errors,warnings,notifications,informational,debugging;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ try {
+ if (op == null) {
+ System.out.println("Please provide valid operation");
+ usage();
+ System.out.println("exec configure-bgp -op [start-bgp-server | stop-bgp-server | add-neighbor | delete-neighbor| graceful-restart| enable-log ]");
+ }
+ switch(op) {
+ case "start-bgp-server":
+ startBgp();
+ break;
+ case "stop-bgp-server":
+ stopBgp();
+ break;
+ case "add-neighbor":
+ addNeighbor();
+ break;
+ case "delete-neighbor":
+ deleteNeighbor();
+ break;
+ case "graceful-restart":
+ configureGR();
+ break;
+ case "enable-log" :
+ enableBgpLogLevel();
+ break;
+ default :
+ System.out.println("invalid operation");
+ usage();
+ System.out.println("exec configure-bgp -op [start-bgp-server | stop-bgp-server | add-neighbor | delete-neighbor| graceful-restart| enable-log ]");
+ }
+ } catch (Exception e) {
+ log.error("failed to handle the command",e);
+ }
+ return null;
+ }
+
+ public boolean validateStalepathTime() {
+ try {
+ int time = Integer.parseInt(stalePathTime);
+ if (time < 30 || time > 3600) {
+ System.out.println("invalid stale path time valid range [30-3600]");
+ printGracefulRestartHelp();
+ return false;
+ }
+ } catch (Exception e) {
+ System.out.println("invalid stale path time");
+ printGracefulRestartHelp();
+ return false;
+ }
+ return true;
+ }
+
+ private void configureGR() throws Exception {
+ boolean validStalepathTime = validateStalepathTime();
+ if (!validStalepathTime) {
+ return;
+ }
+ bgpManager.configureGR(Integer.parseInt(stalePathTime));
+ }
+
+ private void deleteNeighbor() throws Exception {
+ if (ip == null || !validateIp(ip)) {
+ System.out.println("invalid neighbor ip");
+ printDeleteNeighborHelp();
+ return;
+ }
+ long asNo = getAsNumber(ip);
+ if (asNo < 0) {
+ System.out.println("neighbor does not exist");
+ printDeleteNeighborHelp();
+ return;
+ }
+ bgpManager.deleteNeighbor(ip);
+ }
+
+ public long getAsNumber(String nbrIp) {
+ Bgp conf = bgpManager.getConfig();
+ if (conf == null) {
+ return -1;
+ }
+ List<Neighbors> nbrs = conf.getNeighbors();
+ if (nbrs == null) {
+ return -1;
+ }
+ for (Neighbors nbr : nbrs) {
+ if (nbrIp.equals(nbr.getAddress().getValue())) {
+ return nbr.getRemoteAs().longValue();
+ }
+ }
+ return -1;
+ }
+
+ private void stopBgp() throws Exception {
+ Bgp conf = bgpManager.getConfig();
+ if (conf == null) {
+ return;
+ }
+ List<Neighbors> nbrs = conf.getNeighbors();
+ if (nbrs != null && nbrs.size() > 0) {
+ System.err.println("error: all BGP congiguration must be deleted before stopping the router instance");
+ return;
+ }
+ bgpManager.stopBgp();
+ }
+
+ void usage() {
+ System.out.println("usage:");
+ }
+
+ void printStartBgpHelp() {
+ usage();
+ System.out.println("exec configure-bgp -op start-bgp-server --as-num <asnum> --router-id <routerid> [--stalepath-time <time>]");
+ }
+
+ void printAddNeighborHelp() {
+ usage();
+ System.out.println("exec configure-bgp -op add-neighbor --ip <neighbor-ip> --as-num <as-num> [--address-family <af>] [--use-source-ip <sip>] [--ebgp-multihops <em> ]");
+ }
+
+ void printDeleteNeighborHelp() {
+ usage();
+ System.out.println("exec configure-bgp -op delete-neighbor --ip <neighbor-ip>");
+ }
+
+ void printEnableLogHelp() {
+ usage();
+ System.out.println("exec configure-bgp -op enable-logging --filename <filename> --log-level [emergencies|alerts|critical|errors|warnings|notifications|informational|debugging]");
+ }
+
+ void printGracefulRestartHelp() {
+ usage();
+ System.out.println("exec configure-bgp -op graceful-restart --stalepath-time <30-3600>");
+ }
+
+ private void startBgp() throws Exception {
+ boolean validRouterId = false;
+
+ if (bgpManager.getConfig() != null &&
+ bgpManager.getConfig().getAsId() != null) {
+ System.out.println("bgp is already started please use stop-bgp-server and start again");
+ return;
+ }
+ try {
+ long asno = Long.valueOf(asNumber);
+ switch((int)asno) {
+ case 0:
+ case 65535:
+ case 23456:
+ System.out.println("reserved as number supplied ");
+ printStartBgpHelp();
+ return;
+ }
+ if (asno <= 0 || asno > Integer.MAX_VALUE) {
+ System.out.println("invalid as number , supported range [1,"+Integer.MAX_VALUE+"]");
+ printStartBgpHelp();
+ return;
+ }
+ } catch (Exception e) {
+ System.out.println("invalid as number ");
+ printStartBgpHelp();
+ return;
+ }
+ validRouterId = validateIp(routerId);
+ if (!validRouterId) {
+ System.out.println("invalid router id please supply valid ip address");
+ printStartBgpHelp();
+ return;
+ }
+
+ if (stalePathTime != null) {
+ boolean validStalepathTime = validateStalepathTime();
+ if (!validStalepathTime) {
+ return;
+ }
+ }
+ bgpManager.startBgp(Integer.parseInt(asNumber), routerId,
+ stalePathTime == null? 0 : Integer.parseInt(stalePathTime), false);
+ }
+
+ protected void addNeighbor() throws Exception {
+ try {
+ long asno = Long.valueOf(asNumber);
+ switch((int)asno) {
+ case 0:
+ case 65535:
+ case 23456:
+ System.out.println("reserved as number supplied ");
+ printStartBgpHelp();
+ return;
+ }
+ if (asno <= 0 || asno > Integer.MAX_VALUE) {
+ System.out.println("invalid as number , supported range [1,"+Integer.MAX_VALUE+"]");
+ printAddNeighborHelp();
+ return;
+ }
+ } catch (Exception e) {
+ System.out.println("invalid as number");
+ printAddNeighborHelp();
+ return;
+ }
+ boolean validIp = validateIp(ip);
+ if (!validIp) {
+ System.out.println("invalid neighbor ip");
+ printAddNeighborHelp();
+ return;
+ }
+
+ if (sourceIp != null) {
+ validIp = validateIp(sourceIp);
+ if (!validIp) {
+ System.out.println("invalid source ip");
+ printAddNeighborHelp();
+ return;
+ }
+ }
+
+ if (ebgpMultihops != null) {
+ try {
+ long val = Long.valueOf(ebgpMultihops);
+ if (val < 1 || val > 255) {
+ System.out.println("invalid ebgpMultihops number , valid range [1,255] ");
+ printAddNeighborHelp();
+ return;
+ }
+ } catch (Exception e) {
+ System.out.println("invalid ebgpMultihops number, valid range [1-255]");
+ printAddNeighborHelp();
+ return;
+ }
+ }
+ if (addressFamily != null) {
+ try {
+ af_safi.valueOf(addressFamily);
+ } catch (Exception e) {
+ System.out.println("invalid addressFamily valid values SAFI_IPV4_LABELED_UNICAST | SAFI_MPLS_VPN");
+ printAddNeighborHelp();
+ return;
+ }
+ }
+ if (getAsNumber(ip) != -1) {
+ System.out.println("neighbor with ip "+ip+" already exists");
+ return;
+ }
+ bgpManager.addNeighbor(ip, Long.valueOf(asNumber));
+ if (addressFamily != null) {
+ bgpManager.addAddressFamily(ip, af_afi.AFI_IP,
+ af_safi.valueOf(addressFamily));
+ }
+ if (ebgpMultihops != null) {
+ bgpManager.addEbgpMultihop(ip, Integer.parseInt(ebgpMultihops));
+ }
+ if (sourceIp != null) {
+ bgpManager.addUpdateSource(ip, sourceIp);
+ }
+ }
+
+ private boolean validateIp(String inputIp) {
+ boolean validIp = false;
+ try {
+ if (inputIp != null) {
+ InetAddress addr = InetAddress.getByName(inputIp);
+ if (addr.isMulticastAddress()) {
+ System.out.println("ip cannot be multicast address");
+ return false;
+ }
+ if (addr.isLoopbackAddress()) {
+ System.out.println("ip cannot be loopback address");
+ return false;
+ }
+ byte addrBytes[] = addr.getAddress();
+ int lastPart = addrBytes[3] & 0xFF;
+ int firstPart = addrBytes[0] & 0xFF;
+ if (firstPart == 0) {
+ return false;//cannot start with 0 "0.1.2.3"
+ }
+ if (lastPart == 0 || lastPart == 255) {
+ return false;
+ }
+ validIp = true;
+ }
+ } catch (Exception e) {
+ }
+ return validIp;
+ }
+
+ private void enableBgpLogLevel() throws Exception {
+ if (logFile == null) {
+ System.out.println("Please provide log file name ");
+ usage();
+ System.out.println("exec configure-bgp -op enable-log --log-file-path <logfile> --log-level <level>");
+ return;
+ }
+ boolean validLoglevel = false;
+ try {
+ LogLevels.valueOf(logLevel);
+ validLoglevel = true;
+ } catch (Exception e) {
+ }
+ if (!validLoglevel) {
+ System.out.println("Please provide valid log level emergencies|alerts|critical|errors|warnings|notifications|informational|debugging");
+ usage();
+ System.out.println("exec configure-bgp -op enable-log --log-file-path <logfile> --log-level <level>");
+ return;
+ }
+ bgpManager.setQbgpLog(logFile, logLevel);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager;
+import java.util.concurrent.Future;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.bgpmanager.commands.Cache;
+
+@Command(scope = "odl", name = "display-bgp-config", description="")
+public class DisplayBgpConfigCli extends OsgiCommandSupport {
+
+ protected Object doExecute() throws Exception {
+ Cache cache = new Cache();
+ return cache.show();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.FibEntries;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
+
+
+/**
+ * Created by emhamla on 4/14/2015.
+ */
+public class FibDSWriter {
+ private static final Logger logger = LoggerFactory.getLogger(FibDSWriter.class);
+ private final DataBroker broker;
+
+ public FibDSWriter(final DataBroker db) {
+ broker = db;
+ }
+
+ public synchronized void addFibEntryToDS(String rd, String prefix,
+ String nexthop, int label) {
+ if (rd == null || rd.isEmpty()) {
+ logger.error("Prefix {} not associated with vpn", prefix);
+ return;
+ }
+
+ VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).
+ setNextHopAddress(nexthop).setLabel((long)label).build();
+
+ logger.debug("Created vrfEntry for {} nexthop {} label {}", prefix, nexthop, label);
+
+ InstanceIdentifier.InstanceIdentifierBuilder<VrfEntry> idBuilder =
+ InstanceIdentifier.builder(FibEntries.class)
+ .child(VrfTables.class, new VrfTablesKey(rd))
+ .child(VrfEntry.class, new VrfEntryKey(vrfEntry.getDestPrefix()));
+ InstanceIdentifier<VrfEntry> vrfEntryId= idBuilder.build();
+
+ BgpUtil.write(broker, LogicalDatastoreType.CONFIGURATION,
+ vrfEntryId, vrfEntry);
+ }
+
+ public synchronized void removeFibEntryFromDS(String rd, String prefix) {
+
+ if (rd == null || rd.isEmpty()) {
+ logger.error("Prefix {} not associated with vpn", prefix);
+ return;
+ }
+ logger.debug("Removing fib entry with destination prefix {} from vrf table for rd {}", prefix, rd);
+
+ InstanceIdentifierBuilder<VrfEntry> idBuilder =
+ InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(VrfEntry.class, new VrfEntryKey(prefix));
+ InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
+ BgpUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
+
+ }
+
+ public synchronized void removeVrfFromDS(String rd) {
+ logger.debug("Removing vrf table for rd {}", rd);
+
+ InstanceIdentifierBuilder<VrfTables> idBuilder =
+ InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
+ InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
+
+ BgpUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId);
+
+ }
+
+
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.net.Socket;
+import java.net.SocketTimeoutException;
+import java.net.UnknownHostException;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Command(scope = "odl", name = "show-bgp", description = "")
+public class VtyshCli extends OsgiCommandSupport {
+ // public class DisplayBgpConfigCli {
+
+ @Option(name = "--cmd", description = "command to run", required = true, multiValued = false)
+ String cmd = null;
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(VtyshCli.class);
+
+ private static int serverPort = 2605;
+ private static String serverName = "localhost";
+ private static int handlerModule = 0;
+ private static final int BGPd = 1;
+ public static String passwordCheckStr = "Password:";
+ public static String vtyPassword = "sdncbgpc";
+ public static String noPaginationCmd = "terminal length 0";
+ public static int sockTimeout = 5;
+
+ String[] validCommands = new String[]{
+ "display routing ip bgp vpnv4 all",
+ "display routing ip bgp vpnv4 rd <rd>",
+ "display routing ip bgp vpnv4 all neighbors",
+ "display routing ip bgp vpnv4 all neighbors <ip> routes",
+ "display routing ip bgp vpnv4 all <ip/mask>",
+ "display routing ip bgp vpnv4 all summary",
+ "display routing ip bgp vpnv4 all tags",
+ "display routing ip bgp vpnv4 rd <rd> tags",
+ "display routing ip bgp vpnv4 rd <rd> <ip>",
+ "display routing ip bgp vpnv4 rd <rd> <ip/mask>",
+ "display routing ip bgp neighbors",
+ "display routing ip bgp summary",
+ "display routing ip bgp ipv4 unicast",
+ "display routing ip bgp ipv4 unicast <ip/mask>",
+ "display routing bgp neighbors",
+ "display routing bgp neighbors <ip>",
+ "display routing bgp ipv4 unicast <ip>",
+ "display routing bgp ipv4 unicast <ip/mask>"
+ };
+ private static final Logger logger = LoggerFactory.getLogger(VtyshCli.class);
+
+ // @Override
+ protected Object doExecute() throws Exception {
+ String sArg;
+ cmd = cmd.trim();
+ if (cmd.equals("") || cmd.equals("help") ||
+ cmd.equals("-help") || cmd.equals("--help")) {
+ for (String help : validCommands) {
+ System.out.println(help);
+ }
+ return null;
+ }
+ String args[] = cmd.split(" ");
+ if (args.length == 0) {
+ return null;
+ }
+ sArg = args[0];
+ if (sArg == null || sArg.trim().equals("")) {
+ System.out.println("Please provide a valid input.");
+ return null;
+ }
+ switch (sArg) {
+ case "ip":
+ case "bgp":
+ handlerModule = BGPd;
+ break;
+ default:
+ System.out.println("Unknown command");
+ return null;
+ }
+
+ switch (handlerModule) {
+ case BGPd:
+ try {
+ handleCommand(sArg, cmd);
+ } catch (IOException ioe) {
+ System.out.println("IOException thrown.");
+ }
+ break;
+ default:
+ break;
+ }
+ return null;
+ }
+
+ public static void setHostAddr(String hostAddr) {
+ serverName = hostAddr;
+ }
+
+ public String getHostAddr() {
+ return serverName;
+ }
+
+ public static void handleCommand(String arg, String cmd) throws IOException {
+
+ StringBuilder inputBgpCmd = new StringBuilder();
+
+ String str, prompt, replacedStr, inputCmd = null;
+ char cbuf[] = new char[10];
+ char op_buf[];
+ Socket socket = null;
+ PrintWriter out_to_socket = null;
+ BufferedReader in_from_socket = null;
+ StringBuilder sb = new StringBuilder();
+ int ip = 0, ret;
+ StringBuilder temp, temp2;
+ char ch, gt = '>';
+
+ inputBgpCmd.append("show " + cmd);
+
+ inputCmd = inputBgpCmd.toString();
+
+ try {
+ socket = new Socket(serverName, serverPort);
+
+ } catch (UnknownHostException ioe) {
+ System.out.println("No host exists: " + ioe.getMessage());
+ return;
+ } catch (IOException ioe) {
+ System.out.println("I/O error occured " + ioe.getMessage());
+ return;
+ }
+ try {
+ socket.setSoTimeout(sockTimeout * 1000);
+ out_to_socket = new PrintWriter(socket.getOutputStream(), true);
+ in_from_socket = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+
+ } catch (IOException ioe) {
+ System.out.println("IOException thrown.");
+ socket.close();
+ return;
+ }
+ while (true) {
+ try {
+ ret = in_from_socket.read(cbuf);
+
+ } catch (SocketTimeoutException ste) {
+ System.out.println("Read from Socket timed Out while asking for password.");
+ socket.close();
+ return;
+ }
+ if (ret == -1) {
+ System.out.println("Connection closed by BGPd.");
+ socket.close();
+ return;
+ } else {
+ sb.append(cbuf);
+
+ if (sb.toString().contains(passwordCheckStr)) {
+
+ break;
+ }
+ }
+ }
+
+ sb.setLength(0);
+ out_to_socket.println(vtyPassword);
+
+ while (true) {
+ try {
+ ip = in_from_socket.read();
+ } catch (SocketTimeoutException ste) {
+ System.out.println(sb.toString());
+ System.out.println("Read from Socket timed Out while verifying the password.");
+ socket.close();
+ return;
+ }
+ if (ip == (int) gt) {
+ sb.append(gt);
+ break;
+ } else if (ip == -1) {
+ System.out.println(sb.toString());
+ System.out.println("Connection closed by BGPd.");
+ socket.close();
+ return;
+ } else {
+ ch = (char) ip;
+ sb.append(ch);
+
+ }
+ }
+
+ String promptStr = sb.toString();
+ prompt = promptStr.trim();
+ sb.setLength(0);
+ out_to_socket.println(noPaginationCmd);
+ while (true) {
+ try {
+ ip = in_from_socket.read();
+ } catch (SocketTimeoutException ste) {
+ System.out.println(sb.toString());
+ System.out.println("Read from Socket timed Out while sending the term len command..");
+ socket.close();
+ return;
+ }
+ if (ip == (int) gt) {
+ break;
+ } else if (ip == -1) {
+ System.out.println(sb.toString());
+ System.out.println("Connection closed by BGPd.");
+ socket.close();
+ return;
+ } else {
+ ch = (char) ip;
+ sb.append(ch);
+
+ }
+ }
+ sb.setLength(0);
+
+ out_to_socket.println(inputCmd);
+ StringBuffer output = new StringBuffer();
+ String errorMsg = "";
+ while (true) {
+ op_buf = new char[100];
+ temp = new StringBuilder();
+ temp2 = new StringBuilder();
+ try {
+ ret = in_from_socket.read(op_buf);
+
+ } catch (SocketTimeoutException ste) {
+ errorMsg = "Read from Socket timed Out while getting the data.";
+ break;
+ }
+ if (ret == -1) {
+ errorMsg = "Connection closed by BGPd";
+ break;
+ }
+ temp2.append(op_buf);
+
+ if (temp2.toString().contains(inputCmd)) {
+
+ replacedStr = temp2.toString().replaceAll(inputCmd, "");
+ temp.append(replacedStr);
+ temp2.setLength(0);
+
+ } else {
+ temp.append(op_buf);
+ temp2.setLength(0);
+
+ }
+
+ String outputStr = temp.toString();
+ outputStr.replaceAll("^\\s+|\\s+$", "");
+ output.append(outputStr);
+ if (output.toString().trim().endsWith(prompt)) {
+ int index = output.toString().lastIndexOf(prompt);
+ String newString = output.toString().substring(0, index);
+ output.setLength(0);
+ output.append(newString);
+ break;
+ }
+ temp.setLength(0);
+ }
+ System.out.println(output.toString().trim());
+ if (errorMsg.length() > 0) {
+ System.out.println(errorMsg);
+ }
+ socket.close();
+ return;
+
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager.commands;
+
+import org.apache.karaf.shell.commands.*;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.bgpmanager.BgpManager;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.*;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.*;
+import org.opendaylight.yang.gen.v1.urn.ericsson.params.xml.ns.yang.ebgp.rev150901.bgp.neighbors.*;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.*;
+import java.util.*;
+import java.io.*;
+
+@Command(scope = "odl", name = "bgp-cache",
+ description = "Text dump of BGP config cache")
+public class Cache extends OsgiCommandSupport {
+ private static final String LST = "--list";
+ private static final String OFL = "--out-file";
+
+ @Argument(name="dummy", description="Argument not needed",
+ required=false, multiValued = false)
+ private String action = null;
+
+ @Option(name=LST, aliases={"-l"},
+ description="list vrfs and/or networks",
+ required=false, multiValued=true)
+ private List<String> list = null;
+
+ @Option(name=OFL, aliases={"-o"},
+ description="output file",
+ required=false, multiValued=false)
+ private String ofile = null;
+
+ private static final String HTSTR = "Host";
+ private static final String PTSTR = "Port";
+ private static final String ASSTR = "AS-Number";
+ private static final String RISTR = "Router-ID";
+ private static final String SPSTR = "Stale-Path-Time";
+ private static final String FBSTR = "F-bit";
+ private static final String LFSTR = "Log-File";
+ private static final String LLSTR = "Log-Level";
+ private static final String USSTR = "Update-Source";
+ private static final String EBSTR = "EBGP-Multihops";
+ private static final String AFSTR = "Address-Families";
+ private static final String ERSTR = "Export-RTs";
+ private static final String IRSTR = "Import-RTs";
+ private static final String NHSTR = "Nexthop";
+ private static final String LBSTR = "Label";
+ private static final String RDSTR = "RD";
+
+ private Object usage() {
+ System.err.println
+ ("usage: bgp-cache ["+LST+" vrfs | networks] ["+OFL+" file-name]");
+ return null;
+ }
+
+ public Cache() {
+ }
+
+ public Object show() throws Exception {
+ return doExecute();
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ if (!Commands.bgpRunning()) {
+ return null;
+ }
+ Bgp config = Commands.getBgpManager().getConfig();
+ boolean list_vrfs = false;
+ boolean list_nets = false;
+ PrintStream ps = System.out;
+
+ if (action != null) {
+ return usage();
+ }
+ if (ofile != null) {
+ try {
+ ps = new PrintStream(ofile);
+ } catch (Exception e) {
+ System.err.println("error: cannot create file "+ofile +"; exception: "+e);
+ return null;
+ }
+ }
+ if (list != null) {
+ for (String item : list) {
+ switch (item) {
+ case "vrfs" :
+ list_vrfs = true;
+ break;
+ case "networks" :
+ list_nets = true;
+ break;
+ default:
+ System.err.println("error: unknown value for "+LST+": "+item);
+ return null;
+ }
+ }
+ }
+ // we'd normally read this directly from 'config' but
+ // legacy behaviour forces to check for a connection
+ // that's initiated by default at startup without
+ // writing to config.
+ String cHost = Commands.getBgpManager().getConfigHost();
+ int cPort = Commands.getBgpManager().getConfigPort();
+ ps.printf("\nConfiguration Server\n\t%s %s\n\t%s %d\n",
+ HTSTR, cHost, PTSTR, cPort);
+ if (config == null) {
+ return null;
+ }
+ AsId a = config.getAsId();
+ if (a != null) {
+ int asNum = a.getLocalAs().intValue();
+ Ipv4Address routerId = a.getRouterId();
+ Long spt = a.getStalepathTime();
+ Boolean afb = a.isAnnounceFbit();
+ String rid = (routerId == null) ? "<n/a>" : routerId.getValue();
+ int s = (spt == null) ? 0 : spt.intValue();
+ String bit = (afb == null) ? "OFF" : (afb.booleanValue() ? "ON" : "OFF");
+
+ GracefulRestart g = config.getGracefulRestart();
+ if (g != null) {
+ s = g.getStalepathTime().intValue();
+ }
+ ps.printf("\nBGP Router\n");
+ ps.printf("\t%-15s %d\n\t%-15s %s\n\t%-15s %d\n\t%-15s %s\n",
+ ASSTR, asNum, RISTR, rid, SPSTR, s, FBSTR, bit);
+ }
+
+ Logging l = config.getLogging();
+ if (l != null) {
+ ps.printf("\t%-15s %s\n\t%-15s %s\n", LFSTR, l.getFile(),
+ LLSTR, l.getLevel());
+ }
+
+ List<Neighbors> n = config.getNeighbors();
+ if (n != null) {
+ ps.printf("\nNeighbors\n");
+ for (Neighbors nbr : n) {
+ ps.printf("\t%s\n\t\t%-16s %d\n", nbr.getAddress().getValue(),
+ ASSTR, nbr.getRemoteAs().intValue());
+ EbgpMultihop en = nbr.getEbgpMultihop();
+ if (en != null) {
+ ps.printf("\t\t%-16s %d\n", EBSTR, en.getNhops().intValue());
+ }
+ UpdateSource us = nbr.getUpdateSource();
+ if (us != null) {
+ ps.printf("\t\t%-16s %s\n", USSTR, us.getSourceIp().getValue());
+ }
+ ps.printf("\t\t%-16s IPv4-Labeled-VPN", AFSTR);
+ List<AddressFamilies> afs = nbr.getAddressFamilies();
+ if (afs != null) {
+ for (AddressFamilies af : afs) {
+ ps.printf(" %s", af.getSafi().intValue() == 4 ?
+ "IPv4-Labeled-Unicast" : "Unknown");
+ }
+ }
+ ps.printf("\n");
+ }
+ }
+
+ if (list_vrfs) {
+ List<Vrfs> v = config.getVrfs();
+ if (v != null) {
+ ps.printf("\nVRFs\n");
+ for (Vrfs vrf : v) {
+ ps.printf("\t%s\n",vrf.getRd());
+ ps.printf("\t\t%s ", IRSTR);
+ for (String rt : vrf.getImportRts())
+ ps.printf("%s ", rt);
+ ps.printf("\n\t\t%s ", ERSTR);
+ for (String rt : vrf.getExportRts())
+ ps.printf("%s ", rt);
+ ps.printf("\n");
+ }
+ }
+ }
+
+ if (list_nets) {
+ List<Networks> ln = config.getNetworks();
+ if (ln != null) {
+ ps.printf("\nNetworks\n");
+ for (Networks net : ln) {
+ String rd = net.getRd();
+ String pfxlen = net.getPrefixLen();
+ String nh = net.getNexthop().getValue();
+ int label = net.getLabel().intValue();
+ ps.printf("\t%s\n\t\t%-7s %s\n\t\t%-7s %s\n\t\t%-7s %d\n",
+ pfxlen, RDSTR, rd, NHSTR, nh, LBSTR, label);
+ }
+ }
+ }
+ if (ofile != null) {
+ ps.close();
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager.commands;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.SocketException;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Command(scope = "odl", name = "clear-bgp-neighbor", description = "")
+public class ClearBgpCli extends OsgiCommandSupport {
+
+ private static int serverPort = 2605;
+ private static String serverName = "localhost";
+ public static String passwordCheckStr = "Password:";
+ public static String vtyPassword = "sdncbgpc";
+ public static String enableCmd = "enable";
+ public static int sockTimeout = 5;
+ static char HASH_PROMPT = '#';
+ static char GT = '>';
+
+ static final Logger LOGGER = LoggerFactory.getLogger(ClearBgpCli.class);
+
+ @Argument(name="neighbor-ip", description = "neighbor ip to be cleared", required = false, multiValued = false)
+ String nbr = "";
+
+ Socket socket = null;
+ PrintWriter out = null;
+ BufferedReader in = null;
+
+ public static void setHostAddr(String hostAddr) {
+ serverName = hostAddr;
+ }
+
+ protected Object doExecute() throws Exception {
+ if (nbr.isEmpty()) {
+ System.out.println("enter neighbor ip to be cleared");
+ System.out.println("Usage:");
+ System.out.println("odl:clear-bgp-neighbor <neighbor|all>");
+ return null;
+ } else if ("all".equals(nbr)) {
+ nbr = "*";
+ } else {
+ try {
+ InetAddress.getByName(nbr);
+ } catch (Exception e) {
+ System.out.println("Invalid neighbor ip");
+ return null;
+ }
+ }
+ clearBgp("clear ip bgp "+nbr);
+ return null;
+ }
+
+ public static void main(String args[]) throws IOException{
+ ClearBgpCli test = new ClearBgpCli();
+ test.clearBgp("clear ip bgp");
+ }
+
+ public void clearBgp(String clearCommand) throws IOException {
+ try {
+ socket = new Socket(serverName, serverPort);
+ } catch (Exception ioe) {
+ System.out.println("failed to connect to bgpd " + ioe.getMessage());
+ return;
+ }
+ intializeSocketOptions();
+ try {
+ readPassword(in);
+
+ out.println(vtyPassword);
+ out.println("enable");
+ LOGGER.trace("reading until HASH sign");
+ readUntilPrompt(in, HASH_PROMPT);
+
+ out.println(clearCommand);
+ readUntilPrompt(in, HASH_PROMPT);
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ } finally {
+ socket.close();
+ }
+ return;
+
+ }
+
+ private void intializeSocketOptions() throws SocketException, IOException {
+ socket.setSoTimeout(sockTimeout * 1000);
+ out = new PrintWriter(socket.getOutputStream(), true);
+ in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+ }
+
+ private static boolean readPassword(BufferedReader in)
+ throws IOException {
+ return readUntilPrompt(in, GT, passwordCheckStr);
+ }
+
+ private static boolean readUntilPrompt(BufferedReader in, char promptChar)
+ throws IOException {
+ return readUntilPrompt(in, promptChar, null);
+ }
+
+ private static boolean readUntilPrompt(
+ BufferedReader in, char promptChar, String passwordCheckStr)
+ throws IOException {
+ StringBuilder sb = new StringBuilder();
+ int ret = 0;
+ while (true) {
+ ret = in.read();
+ if (ret == -1) {
+ throw new IOException("connection closed by bgpd");
+ } else if (ret == promptChar) {
+ return true;
+ }
+
+ sb.append((char)ret);
+ if (passwordCheckStr != null) {
+ if (sb.toString().contains(passwordCheckStr)) {
+ break;
+ }
+ }
+ }
+ sb.setLength(0);
+ return true;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager.commands;
+
+import org.opendaylight.bgpmanager.BgpManager;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.*;
+
+public class Commands {
+ private static BgpManager bm;
+ public static final int IPADDR = 1;
+ public static final int INT = 2;
+
+ public Commands(BgpManager bgpm) {
+ bm = bgpm;
+ }
+
+ public static BgpManager getBgpManager() {
+ return bm;
+ }
+
+ public static boolean isValid(String val, int type, String name) {
+ switch (type) {
+ case INT :
+ try {
+ int i = Integer.parseInt(val);
+ } catch (NumberFormatException nme) {
+ System.err.println("error: value of "+name+" is not an integer");
+ return false;
+ }
+ break;
+ case IPADDR:
+ try {
+ Ipv4Address addr = new Ipv4Address(val);
+ } catch (Exception e) {
+ System.err.println("error: value of "+name+" is not an IP address");
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
+
+ public static boolean bgpRunning() {
+ if (getBgpManager() == null) {
+ System.err.println("error: cannot run command, BgpManager not started");
+ return false;
+ }
+ return true;
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager.commands;
+
+import org.apache.karaf.shell.commands.*;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.bgpmanager.BgpManager;
+
+@Command(scope = "odl", name = "bgp-connect",
+ description = "Add or delete client connection to BGP Config Server")
+public class Connect extends OsgiCommandSupport {
+ private static final String HOST = "--host";
+ private static final String PORT = "--port";
+
+ @Argument(name="add|del", description="The desired operation",
+ required=true, multiValued = false)
+ String action = null;
+
+ @Option(name=HOST, aliases={"-h"},
+ description="IP address of the server",
+ required=false, multiValued=false)
+ String host = null;
+
+ @Option(name=PORT, aliases={"-p"},
+ description="Thrift port", required=false,
+ multiValued=false)
+ String port = null;
+
+ private Object usage() {
+ System.err.println(
+ "usage: bgp-connect ["+HOST+" h] ["+PORT+" p] <add | del>");
+ return null;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ if (!Commands.bgpRunning()) {
+ return null;
+ }
+ BgpManager bm = Commands.getBgpManager();
+ switch (action) {
+ case "add" :
+ if (host == null || port == null) {
+ System.err.println("error: "+HOST+" and "+PORT+" needed");
+ return null;
+ }
+ if (!Commands.isValid(host, Commands.IPADDR, HOST)
+ || !Commands.isValid(port, Commands.INT, PORT)) {
+ return null;
+ }
+ // check: already connected?
+ bm.startConfig(host, Integer.valueOf(port));
+ break;
+ case "del" :
+ if (host != null || port != null) {
+ System.err.println("note: option(s) not needed; ignored");
+ }
+ // check: nothing to stop?
+ bm.stopConfig();
+ break;
+ default :
+ return usage();
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager.commands;
+
+import org.apache.karaf.shell.commands.*;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.bgpmanager.BgpManager;
+
+@Command(scope = "odl", name = "bgp-misc",
+ description = "Add or delete miscellaneous BGP config options")
+public class Misc extends OsgiCommandSupport {
+ private static final String LF = "--log-file";
+ private static final String LL = "--log-level";
+ private static final String SP = "--stalepath-time";
+
+ @Argument(name="add|del", description="The desired operation",
+ required=true, multiValued = false)
+ private String action = null;
+
+ @Option(name=LF, aliases={"-f"},
+ description="Log file name",
+ required=false, multiValued=false)
+ private String file = null;
+
+ @Option(name=LL, aliases={"-l"},
+ description="Log level", required=false,
+ multiValued=false)
+ private String level = null;
+
+ @Option(name=SP, aliases={"-s"},
+ description="Stale-path time", required=false,
+ multiValued=false)
+ private String spt = null;
+
+ private Object usage() {
+ System.err.println(
+ "usage: bgp-misc [<"+LF+" name> <"+LL+" level>] ["
+ +SP+" stale-path-time] <add | del>");
+ return null;
+ }
+
+ private boolean isValidLevel(String level) {
+ switch (level) {
+ case "emergencies":
+ case "alerts":
+ case "critical":
+ case "errors":
+ case "warnings":
+ case "notifications":
+ case "informational":
+ case "debugging":
+ return true;
+ default:
+ break;
+ }
+ return false;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ if (!Commands.bgpRunning()) {
+ return null;
+ }
+ if (spt == null && file == null && level == null) {
+ return usage();
+ }
+ if (file != null ^ level != null) {
+ return usage();
+ }
+ if (level != null && !isValidLevel(level)) {
+ System.err.println("error: invalid value for "+LL);
+ return null;
+ }
+ BgpManager bm = Commands.getBgpManager();
+ switch (action) {
+ case "add" :
+ if (spt != null && Commands.isValid(spt, Commands.INT, SP)) {
+ int s = Integer.valueOf(spt);
+ bm.configureGR(s);
+ }
+ if (file != null && level != null)
+ bm.setQbgpLog(file, level);
+ break;
+ case "del" :
+ if (spt != null) {
+ bm.delGracefulRestart();
+ }
+ if (file != null && level != null) {
+ bm.delLogging();
+ }
+ break;
+ default :
+ return usage();
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager.commands;
+
+import org.apache.karaf.shell.commands.*;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.bgpmanager.BgpManager;
+import org.opendaylight.bgpmanager.thrift.gen.af_afi;
+import org.opendaylight.bgpmanager.thrift.gen.af_safi;
+
+@Command(scope = "odl", name = "bgp-nbr",
+ description = "Add or delete BGP neighbor")
+public class Neighbor extends OsgiCommandSupport {
+ private static final String IP = "--ip-address";
+ private static final String AS = "--as-number";
+ private static final String MH = "--ebgp-multihop";
+ private static final String US = "--update-source";
+ private static final String AF = "--address-family";
+
+ @Argument(index=0, name="add|del", description="The desired operation",
+ required=true, multiValued = false)
+ String action = null;
+
+ @Option(name=IP, aliases = {"-i"},
+ description="Neighbor's IP address",
+ required=false, multiValued=false)
+ String nbrIp = null;
+
+ @Option(name=AS, aliases = {"-a"},
+ description="AS number",
+ required=false, multiValued=false)
+ String asNum = null;
+
+ @Option(name=MH, aliases = {"-e"},
+ description="EBGP-multihop hops",
+ required=false, multiValued=false)
+ String nHops = null;
+
+ @Option(name=US, aliases = {"-u"},
+ description="Update source address",
+ required=false, multiValued=false)
+ String srcIp = null;
+
+ @Option(name=AF, aliases = {"-f"},
+ description="Address family",
+ required=false, multiValued=false)
+ String addrFamily = null;
+
+ private Object usage() {
+ System.err.println(
+ "usage: bgp-nbr ["+IP+" nbr-ip-address] ["+AS+" asnum] ["
+ +MH+" hops] ["+US+" source] ["+AF+" lu] <add|del>");
+ return null;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ if (!Commands.bgpRunning()) {
+ return null;
+ }
+ BgpManager bm = Commands.getBgpManager();
+ switch (action) {
+ case "add" :
+ if (nbrIp == null) {
+ System.err.println("error: "+IP+" needed");
+ return null;
+ }
+ int asn = bm.getConfig().getAsId().getLocalAs().intValue();
+ int hops = 0;
+ if (!Commands.isValid(nbrIp, Commands.IPADDR, IP)) {
+ return null;
+ }
+ if (asNum != null) {
+ if (!Commands.isValid(asNum, Commands.INT, AS)) {
+ return null;
+ } else {
+ asn = Integer.valueOf(asNum);
+ }
+ }
+ bm.addNeighbor(nbrIp, asn);
+ if (nHops != null) {
+ if (!Commands.isValid(nHops, Commands.INT, MH)) {
+ return null;
+ } else {
+ hops = Integer.valueOf(nHops);
+ }
+ bm.addEbgpMultihop(nbrIp, hops);
+ }
+ if (srcIp != null) {
+ if (!Commands.isValid(srcIp, Commands.IPADDR, US)) {
+ return null;
+ }
+ bm.addUpdateSource(nbrIp, srcIp);
+ }
+ if (addrFamily != null) {
+ if (!addrFamily.equals("lu")) {
+ System.err.println("error: "+AF+" must be lu");
+ return null;
+ }
+ af_afi afi = af_afi.findByValue(1);
+ af_safi safi = af_safi.findByValue(4);
+ bm.addAddressFamily(nbrIp, afi, safi);
+ }
+ break;
+ case "del" :
+ if (nbrIp == null) {
+ System.err.println("error: "+IP+" needed");
+ return null;
+ }
+ if (!Commands.isValid(nbrIp, Commands.IPADDR, IP)) {
+ return null;
+ }
+ if (asNum != null || nHops != null || srcIp != null
+ || addrFamily != null) {
+ System.err.println("note: some option(s) not needed; ignored");
+ }
+ bm.deleteNeighbor(nbrIp);
+ break;
+ default :
+ return usage();
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager.commands;
+
+import org.apache.karaf.shell.commands.*;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.bgpmanager.BgpManager;
+import org.opendaylight.bgpmanager.thrift.gen.qbgpConstants;
+
+@Command(scope = "odl", name = "bgp-network",
+ description = "Add or delete BGP static routes")
+public class Network extends OsgiCommandSupport {
+ private static final String RD = "--rd";
+ private static final String PFX = "--prefix";
+ private static final String NH = "--nexthop";
+ private static final String LB = "--label";
+
+ @Argument(name="add|del", description="The desired operation",
+ required=true, multiValued = false)
+ private String action = null;
+
+ @Option(name=RD, aliases={"-r"},
+ description="Route distinguisher",
+ required=false, multiValued=false)
+ private String rd = null;
+
+ @Option(name=PFX, aliases={"-p"},
+ description="prefix/length",
+ required=false, multiValued=false)
+ private String pfx = null;
+
+ @Option(name=NH, aliases={"-n"},
+ description="Nexthop",
+ required=false, multiValued=false)
+ private String nh = null;
+
+ @Option(name=LB, aliases={"-l"},
+ description="Label",
+ required=false, multiValued=false)
+ private String lbl = null;
+
+ private Object usage() {
+ System.err.println(
+ "usage: bgp-network ["+RD+" rd] ["+PFX+" prefix/len] ["
+ +NH+" nexthop] ["+LB+" label] <add|del>");
+ return null;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ if (!Commands.bgpRunning()) {
+ return null;
+ }
+ BgpManager bm = Commands.getBgpManager();
+ switch (action) {
+ case "add" :
+ int label = qbgpConstants.LBL_EXPLICIT_NULL;
+ if (pfx == null ) {
+ System.err.println("error: "+PFX+" is needed");
+ return null;
+ }
+ if (nh == null) {
+ System.err.println("error: "+NH+" is needed");
+ return null;
+ }
+ //todo: syntactic validation of prefix
+ if (!Commands.isValid(nh, Commands.IPADDR, NH)) {
+ return null;
+ }
+ if (lbl != null) {
+ if (!Commands.isValid(lbl, Commands.INT, LB)) {
+ return null;
+ } else {
+ label = Integer.valueOf(lbl);
+ }
+ } else if (rd == null) {
+ System.err.println("error: "+RD+" is needed");
+ return null;
+ }
+ bm.addPrefix(rd, pfx, nh, label);
+ break;
+ case "del" :
+ if (pfx == null) {
+ System.err.println("error: "+PFX+" is needed");
+ return null;
+ }
+ if (nh != null || lbl != null) {
+ System.err.println("note: some option(s) not needed; ignored");
+ }
+ bm.deletePrefix(rd, pfx);
+ break;
+ default :
+ return usage();
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager.commands;
+
+import org.apache.karaf.shell.commands.*;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.bgpmanager.BgpManager;
+
+@Command(scope = "odl", name = "bgp-rtr",
+ description = "Add or delete BGP router instance")
+public class Router extends OsgiCommandSupport {
+ private static final String AS = "--as-number";
+ private static final String RID = "--router-id";
+ private static final String SP = "--stale-path-time";
+ private static final String FB = "--f-bit";
+
+ @Argument(name="add|del", description="The desired operation",
+ required=true, multiValued = false)
+ private String action = null;
+
+ @Option(name=AS, aliases={"-a"},
+ description="AS number",
+ required=false, multiValued=false)
+ private String asNum = null;
+
+ @Option(name=RID, aliases={"-r"},
+ description="Router ID",
+ required=false, multiValued=false)
+ private String rid = null;
+
+ @Option(name=SP, aliases={"-s"},
+ description="Stale-path time",
+ required=false, multiValued=false)
+ private String spt = null;
+
+ @Option(name=FB, aliases={"-f"},
+ description="F-bit",
+ required=false, multiValued=false)
+ private String fbit = null;
+
+ private Object usage() {
+ System.err.println(
+ "usage: bgp-rtr ["+AS+" as-number] ["+RID+" router-id] ["
+ +SP+" stale-path-time] ["+FB+" on|off] <add | del>");
+ return null;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ if (!Commands.bgpRunning()) {
+ return null;
+ }
+ BgpManager bm = Commands.getBgpManager();
+ switch (action) {
+ case "add" :
+ // check: rtr already running?
+ int asn = 0;
+ int s = 0;
+ boolean fb = false;
+ if (asNum == null) {
+ System.err.println("error: "+AS+" is needed");
+ return null;
+ }
+ if (!Commands.isValid(asNum, Commands.INT, AS)) {
+ return null;
+ }
+ asn = Integer.valueOf(asNum);
+ if (rid != null &&
+ !Commands.isValid(rid, Commands.IPADDR, RID)) {
+ return null;
+ }
+ if (spt != null) {
+ if (!Commands.isValid(spt, Commands.INT, SP)) {
+ return null;
+ } else {
+ s = Integer.valueOf(spt);
+ }
+ }
+ if (fbit != null) {
+ switch (fbit) {
+ case "on":
+ fb = true;
+ break;
+ case "off":
+ fb = false;
+ break;
+ default:
+ System.err.println("error: "+FB+" must be on or off");
+ return null;
+ }
+ }
+ bm.startBgp(asn, rid, s, fb);
+ break;
+ case "del" :
+ // check: nothing to stop?
+ if (asNum != null || rid != null || spt != null ||
+ fbit != null) {
+ System.err.println("note: option(s) not needed; ignored");
+ }
+ bm.stopBgp();
+ break;
+ default :
+ return usage();
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager.commands;
+
+import org.apache.karaf.shell.commands.*;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.bgpmanager.BgpManager;
+import java.util.*;
+
+@Command(scope = "odl", name = "bgp-vrf",
+ description = "Add or delete BGP VRFs")
+public class Vrf extends OsgiCommandSupport {
+ private static final String RD = "--rd";
+ private static final String IR = "--import-rts";
+ private static final String ER = "--export-rts";
+
+ @Argument(name="add|del", description="The desired operation",
+ required=true, multiValued = false)
+ private String action = null;
+
+ @Option(name=RD, aliases={"-r"},
+ description="Route distinguisher",
+ required=false, multiValued=false)
+ private String rd = null;
+
+ @Option(name=IR, aliases={"-i"},
+ description="Import route-targets",
+ required=false, multiValued=true)
+ private List<String> irts = null;
+
+ @Option(name=ER, aliases={"-e"},
+ description="Export route-targets",
+ required=false, multiValued=true)
+ private List<String> erts = null;
+
+ private Object usage() {
+ System.err.println(
+ "usage: bgp-vrf ["+RD+" rd] [<"+IR+" | "+ER+"> rt1] .. [<"+
+ IR+" | "+ER+"> rtN] <add|del>");
+ return null;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ if (!Commands.bgpRunning()) {
+ return null;
+ }
+ BgpManager bm = Commands.getBgpManager();
+ switch (action) {
+ case "add" :
+ if (rd == null || irts == null || erts == null) {
+ System.err.println("error: all options needed");
+ return null;
+ }
+ // check: rd exists? rd & rt's in format?
+ bm.addVrf(rd, irts, erts);
+ break;
+ case "del" :
+ if (rd == null) {
+ System.err.println("error: "+RD+" needed");
+ return null;
+ }
+ if (irts != null || erts != null) {
+ System.err.println("error: some option(s) not needed; ignored");
+ }
+ // check: rd exists? in format?
+ bm.deleteVrf(rd);
+ break;
+ default :
+ return usage();
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager.oam;
+
+/**
+ * Created by echiapt on 7/27/2015.
+ */
+
+ import javax.management.*;
+
+ import org.slf4j.Logger;
+ import org.slf4j.LoggerFactory;
+
+ import java.util.ArrayList;
+
+public class BgpAlarmBroadcaster extends NotificationBroadcasterSupport implements BgpAlarmBroadcasterMBean {
+ private static final Logger LOGGER = LoggerFactory.getLogger(BgpAlarmBroadcaster.class);
+ private long sequenceNumber;
+ public BgpAlarmBroadcaster () {
+ this.sequenceNumber = 1;
+ }
+
+ public void sendBgpAlarmInfo(String pfx, int code , int subcode) {
+ Notification n;
+ String alarmAddText, alarmSrc = "BGP";
+ BgpAlarmErrorCodes userAlarm;
+ ArrayList<String> arrayList = new ArrayList<String>();
+
+ userAlarm = BgpAlarmErrorCodes.checkErrorSubcode(subcode);
+ alarmAddText = "Peer=" + pfx;
+ arrayList.clear();
+ arrayList.add(userAlarm.getAlarmType());
+ arrayList.add(alarmAddText);
+ arrayList.add(alarmSrc);
+ n = new AttributeChangeNotification(this, sequenceNumber++, System.currentTimeMillis(),
+ "raise Alarm Object notified", "raiseAlarmObject",
+ "ArrayList", "", arrayList);
+ sendNotification(n);
+ LOGGER.info("BGP: Alarm :"+ userAlarm.getAlarmType() + " has been posted.");
+ return;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager.oam;
+
+/**
+ * Created by ECHIAPT on 8/3/2015.
+ * Interface to publish methods for Alarms Notifications implemented by AlarmBroadcaster.
+ */
+public interface BgpAlarmBroadcasterMBean {
+
+ public void sendBgpAlarmInfo(String pfx, int code , int subcode);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager.oam;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Created by echiapt on 7/27/2015.
+ */
+public enum BgpAlarmErrorCodes {
+ CEASE_MAX_PREFIX (1, "BgpMaxPrefixesFailure"),
+ CEASE_PEER_UNCONFIG (3, "BgpPeerUnconfigFailure") ,
+ CEASE_CONNECT_REJECT (5, "BgpConnRejectFailure"),
+ CEASE_COLLISION_RESOLUTION (7, "BgpCollisionResolutionFailure"),
+ CEASE_OUT_OF_RESOURCE (8, "BgpOutOfResourcesFailure"),
+ ERROR_IGNORE (-1,"UnknownErr");
+
+ private final int error;
+ private final String alarmType;
+
+ BgpAlarmErrorCodes(int error, String alarmType) {
+ this.error = error;
+ this.alarmType = alarmType;
+ }
+
+ private static final Map<Integer, BgpAlarmErrorCodes> intToTypeMap = new HashMap<Integer, BgpAlarmErrorCodes>();
+ static {
+ for (BgpAlarmErrorCodes type : BgpAlarmErrorCodes.values()) {
+ intToTypeMap.put(type.error, type);
+ }
+
+ }
+
+ public String getAlarmType() {
+ return this.alarmType;
+ }
+
+ public static BgpAlarmErrorCodes checkErrorSubcode(int i) {
+ BgpAlarmErrorCodes type = intToTypeMap.get(Integer.valueOf(i));
+ if (type == null)
+ return BgpAlarmErrorCodes.ERROR_IGNORE;
+ return type;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager.oam;
+
+
+public class BgpConstants {
+
+ public static final String BGP_SPEAKER_HOST_NAME = "vpnservice.bgpspeaker.host.name";
+ public static final String BGP_SPEAKER_THRIFT_PORT = "vpnservice.bgpspeaker.thrift.port";
+ public static final String DEFAULT_BGP_HOST_NAME = "localhost";
+ public static final int DEFAULT_BGP_THRIFT_PORT = 7644;
+ public static final int BGP_NOTIFY_CEASE_CODE = 6;
+ public static final String QBGP_VTY_PASSWORD = "sdncbgpc";
+ public static final String BGP_COUNTER_NBR_PKTS_RX = "BgpNeighborPacketsReceived";
+ public static final String BGP_COUNTER_NBR_PKTS_TX = "BgpNeighborPacketsSent";
+ public static final String BGP_COUNTER_RD_ROUTE_COUNT = "BgpRdRouteCount";
+ public static final String BGP_COUNTER_TOTAL_PFX = "BgpTotalPrefixes";
+ public static final String BGP_DEF_LOG_LEVEL = "errors";
+ public static final String BGP_DEF_LOG_FILE = "/var/log/bgp_debug.log";
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager.oam;
+
+import javax.management.Attribute;
+import javax.management.JMException;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import java.io.*;
+import java.lang.management.ManagementFactory;
+import java.net.*;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+//import org.opendaylight.bgpmanager.globals.BgpConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Created by ECHIAPT on 8/4/2015.
+ */
+public class BgpCounters extends TimerTask {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(BgpCounters.class);
+ public static BgpCountersBroadcaster bgpStatsBroadcaster = null;
+ public MBeanServer bgpStatsServer = null;
+ public Map <String, String> countersMap = new HashMap<String, String>();
+
+ @Override
+ public void run () {
+ try {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Fetching counters from BGP at " + new Date());
+ }
+ resetCounters();
+ fetchCmdOutputs("cmd_ip_bgp_summary.txt","show ip bgp summary");
+ fetchCmdOutputs("cmd_bgp_ipv4_unicast_statistics.txt", "show bgp ipv4 unicast statistics");
+ fetchCmdOutputs("cmd_ip_bgp_vpnv4_all.txt", "show ip bgp vpnv4 all");
+ parse_ip_bgp_summary();
+ parse_bgp_ipv4_unicast_statistics();
+ parse_ip_bgp_vpnv4_all();
+ if (LOGGER.isDebugEnabled()) {
+ dumpCounters();
+ }
+ if (bgpStatsBroadcaster == null) {
+ //First time execution
+ try {
+ bgpStatsBroadcaster = new BgpCountersBroadcaster();
+ bgpStatsServer = ManagementFactory.getPlatformMBeanServer();
+ ObjectName bgpStatsObj = new ObjectName("SDNC.PM:type=BgpCountersBroadcaster");
+ bgpStatsServer.registerMBean(bgpStatsBroadcaster, bgpStatsObj);
+ LOGGER.info("BGP Counters MBean Registered :::");
+ } catch (JMException e) {
+ LOGGER.error("Adding a NotificationBroadcaster failed." , e);
+ return;
+ }
+ }
+ bgpStatsBroadcaster.setBgpCountersMap(countersMap);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Finished updating the counters from BGP at " + new Date());
+ }
+ } catch (Exception e) {
+ LOGGER.error("Failed to publish bgp counters ", e);
+ }
+ }
+
+ public void dumpCounters () {
+ Iterator<Map.Entry<String, String>> entries = countersMap.entrySet().iterator();
+ while (entries.hasNext()) {
+ Map.Entry<String, String> entry = entries.next();
+ LOGGER.debug(entry.getKey() + ", Value = " + entry.getValue());
+ }
+ }
+
+ public static void fetchCmdOutputs (String filename, String cmdName) throws IOException {
+ Socket socket;
+ int serverPort = 2605;
+ String serverName = BgpConstants.DEFAULT_BGP_HOST_NAME;
+ int sockTimeout = 2;
+ PrintWriter out_to_socket;
+ BufferedReader in_from_socket;
+ char cbuf[] = new char[10];
+ char op_buf[];
+ StringBuilder sb = new StringBuilder();
+ int ip, ret;
+ StringBuilder temp;
+ char ch, gt = '>', hash = '#';
+ String vtyPassword = BgpConstants.QBGP_VTY_PASSWORD;
+ String passwordCheckStr = "Password:";
+ String enableString = "en";
+ String prompt, replacedStr;
+
+ try
+ {
+ socket = new Socket(serverName, serverPort);
+
+ }
+ catch (UnknownHostException ioe) {
+ LOGGER.error("No host exists: " + ioe.getMessage());
+ return;
+ }
+ catch (IOException ioe) {
+ LOGGER.error("I/O error occured " + ioe.getMessage());
+ return;
+ }
+ try {
+ socket.setSoTimeout(sockTimeout*1000);
+ out_to_socket = new PrintWriter(socket.getOutputStream(), true);
+ in_from_socket = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+
+ } catch (IOException ioe) {
+ LOGGER.error("IOException thrown.");
+ socket.close();
+ return;
+ }
+ while (true) {
+ try {
+ ret = in_from_socket.read(cbuf);
+ }
+ catch (SocketTimeoutException ste) {
+ LOGGER.error("Read from Socket timed Out while asking for password.");
+ socket.close();
+ return;
+ }
+ catch (IOException ioe) {
+ LOGGER.error("Caught IOException");
+ socket.close();
+ return;
+ }
+ if (ret == -1) {
+ LOGGER.error("Connection closed by BGPd.");
+ socket.close();
+ return;
+ } else {
+ sb.append(cbuf);
+ if (sb.toString().contains(passwordCheckStr)) {
+ break;
+ }
+ }
+ }
+
+ sb.setLength(0);
+ out_to_socket.println(vtyPassword);
+
+ while (true) {
+ try {
+ ip = in_from_socket.read();
+ }
+ catch (SocketTimeoutException ste) {
+ LOGGER.error(sb.toString());
+ LOGGER.error("Read from Socket timed Out while verifying the password.");
+ socket.close();
+ return;
+ }
+ if (ip == (int)gt) {
+ break;
+ } else if (ip == -1) {
+ LOGGER.error(sb.toString());
+ LOGGER.error("Connection closed by BGPd.");
+ socket.close();
+ return;
+ } else {
+ ch = (char)ip;
+ sb.append(ch);
+
+ }
+ }
+
+ prompt = sb.toString();
+ prompt = prompt.trim();
+ sb.setLength(0);
+ out_to_socket.println(enableString);
+
+ while (true) {
+ try {
+ ip = in_from_socket.read();
+ }
+ catch (SocketTimeoutException ste) {
+ LOGGER.error(sb.toString());
+ LOGGER.error("Read from Socket timed Out while keying the en keyword.");
+ socket.close();
+ return;
+ }
+ if (ip == (int)hash) {
+ break;
+ } else if (ip == -1) {
+ LOGGER.error(sb.toString());
+ LOGGER.error("Connection closed by BGPd.");
+ socket.close();
+ return;
+ } else {
+ ch = (char)ip;
+ sb.append(ch);
+
+ }
+ }
+ sb.setLength(0);
+ temp = new StringBuilder();
+ File file;
+ FileWriter fileWritter;
+ BufferedWriter bufferWritter;
+
+ try {
+ file = new File(filename);
+ if (!file.exists()) {
+ file.createNewFile();
+ }
+ fileWritter = new FileWriter(file.getName(), true);
+ bufferWritter = new BufferedWriter(fileWritter);
+ } catch (IOException e) {
+ return;
+ }
+ out_to_socket.println(cmdName);
+ temp.setLength(0);
+ while (true) {
+ try {
+ op_buf = new char[100];
+ ret = in_from_socket.read(op_buf);
+
+ } catch (SocketTimeoutException ste) {
+ break;
+ } catch (SocketException soc) {
+ break;
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ break;
+ }
+
+ if (ret == -1) {
+ break;
+ }
+ temp.append(op_buf);
+ }
+ String outputStr = temp.toString();
+ StringBuffer output = new StringBuffer();
+
+ outputStr.replaceAll("^\\s+|\\s+$", "");
+ output.append(outputStr);
+ if (output.toString().trim().contains(prompt)) {
+ int index = output.toString().lastIndexOf(prompt);
+ String newString = output.toString().substring(0, index);
+ output.setLength(0);
+ output.append(newString);
+ }
+ try {
+ bufferWritter.write(output.toString().trim());
+ temp.setLength(0);
+ } catch (IOException e) {
+ e.printStackTrace();
+ return;
+ }
+ try {
+ bufferWritter.close();
+ fileWritter.close();
+ socket.close();
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ return;
+ }
+ }
+
+ public boolean validate(final String ip){
+ if (ip == null || ip.equals("")) {
+ return false;
+ }
+ final String PATTERN =
+ "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
+ Pattern pattern = Pattern.compile(PATTERN);
+ Matcher matcher = pattern.matcher(ip);
+ return matcher.matches();
+ }
+
+
+ /*
+ * The below function parses the output of "show ip bgp summary" saved in a file.
+ * Below is the snippet for the same :-
+ <output>
+ BGP router identifier 10.183.254.53, local AS number 101
+ .....
+ Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
+ 10.183.254.76 4 100 3 4 0 0 0 00:01:27 0
+ .........
+ Total number of neighbors 1
+ </output>
+ */
+
+ public void parse_ip_bgp_summary() {
+ File file = new File("cmd_ip_bgp_summary.txt");
+ Scanner scanner;
+ String lineFromFile;
+ List<String> inputStrs = new ArrayList<String>();
+ int i = 0;
+ String as,rx, tx;
+ boolean startEntries = false;
+ String[] result;
+ String StrIP;
+
+ try {
+ scanner = new Scanner(file);
+ } catch (IOException e) {
+ LOGGER.error("Could not process the file " + file.getAbsolutePath());
+ return ;
+ }
+ while (scanner.hasNextLine()) {
+
+ lineFromFile = scanner.nextLine();
+ inputStrs.add(lineFromFile);
+ }
+ String str;
+ StringBuilder NbrInfoKey = new StringBuilder();
+
+ while (i < inputStrs.size()) {
+ str = inputStrs.get(i);
+ if (str.contains("State/PfxRcd")) {
+ startEntries = true;
+ } else if (startEntries == true) {
+ result = str.split("\\s+");
+ try {
+ StrIP = result[0].trim();
+ if (!validate(StrIP)) {
+ return;
+ }
+ as = result[2];
+ rx = result[3];
+ tx = result[4];
+
+ NbrInfoKey.setLength(0);
+ NbrInfoKey.append(BgpConstants.BGP_COUNTER_NBR_PKTS_RX).append(":").
+ append("BGP_Nbr_IP_").append(StrIP).append("_AS_").append(as).append("_PktsReceived");
+ countersMap.put(NbrInfoKey.toString(), rx);
+
+
+ NbrInfoKey.setLength(0);
+ NbrInfoKey.append(BgpConstants.BGP_COUNTER_NBR_PKTS_TX).append(":").
+ append("BGP_Nbr_IP_").append(StrIP).append("_AS_").append(as).append("_PktsSent");
+ countersMap.put(NbrInfoKey.toString(), tx);
+ } catch (Exception e) {
+ return;
+ }
+ }
+ i++;
+ }
+ }
+ /*
+ * The below function parses the output of "show bgp ipv4 unicast statistics" saved in a file.
+ * Below is the sample output for the same :-
+ <output>
+ BGP IPv4 Unicast RIB statistics
+ ...
+ Total Prefixes : 8
+ ......
+ </output>
+ */
+
+ public void parse_bgp_ipv4_unicast_statistics() {
+ File file = new File("cmd_bgp_ipv4_unicast_statistics.txt");
+ Scanner scanner;
+ String lineFromFile;
+ StringBuilder key = new StringBuilder();
+ String totPfx = "";
+ List<String> inputStrs = new ArrayList<String>();
+ try {
+ scanner = new Scanner(file);
+ } catch (IOException e) {
+ System.err.println("Could not process the file " + file.getAbsolutePath());
+ return ;
+ }
+ while (scanner.hasNextLine()) {
+
+ lineFromFile = scanner.nextLine();
+ inputStrs.add(lineFromFile);
+ }
+
+ int i = 0;
+ String instr;
+ while (i < inputStrs.size()) {
+ instr = inputStrs.get(i);
+ if (instr.contains("Total Prefixes")) {
+ String[] result = instr.split(":");
+ try {
+ totPfx = result[1].trim();
+ } catch (Exception e) {
+ totPfx = "0";
+ }
+ break;
+ }
+ i++;
+ }
+ key.setLength(0);
+ key.append(BgpConstants.BGP_COUNTER_TOTAL_PFX).append(":").
+ append("Bgp_Total_Prefixes");
+ countersMap.put(key.toString(), totPfx);
+ }
+
+ /*
+ * The below function parses the output of "show ip bgp vpnv4 all" saved in a file.
+ * Below is the sample output for the same :-
+ * show ip bgp vpnv4 all
+ <output>
+ BGP table version is 0, local router ID is 10.183.181.21
+ ......
+ Route Distinguisher: 100:1
+ *>i15.15.15.15/32 10.183.181.25 0 100 0 ?
+ *>i17.18.17.17/32 10.183.181.25 0 100 0 ?
+ *>i17.18.17.17/32 10.183.181.25 0 100 0 ?
+ *>i17.18.17.17/32 10.183.181.25 0 100 0 ?
+ Route Distinguisher: 100:2
+ *>i16.16.16.16/32 10.183.181.25 0 100 0 ?
+ *>i18.18.18.18/32 10.183.181.25 0 100 0 ?
+ *>i17.18.17.17/32 10.183.181.25 0 100 0 ?
+ </output>
+ */
+ public void parse_ip_bgp_vpnv4_all() {
+ File file = new File("cmd_ip_bgp_vpnv4_all.txt");
+ Scanner scanner;
+ String lineFromFile;
+ List<String> inputStrs = new ArrayList<String>();
+
+ try {
+ scanner = new Scanner(file);
+ } catch (IOException e) {
+ System.err.println("Could not process the file " + file.getAbsolutePath());
+ return ;
+ }
+ while (scanner.hasNextLine()) {
+ lineFromFile = scanner.nextLine();
+ inputStrs.add(lineFromFile);
+ }
+ int i = 0;
+ String instr, rd;
+ while (i < inputStrs.size()) {
+ instr = inputStrs.get(i);
+ if (instr.contains("Route Distinguisher")) {
+ String[] result = instr.split(":");
+ rd = result[1].trim() + "_" + result[2].trim();
+ i = processRouteCount(rd, i + 1, inputStrs);
+
+ }
+ i++;
+ }
+
+ }
+
+ public int processRouteCount(String rd, int startIndex, List<String> inputStrs) {
+ int num = startIndex, route_count = 0;
+ String str;
+ StringBuilder key = new StringBuilder();
+ str = inputStrs.get(num);
+
+ while (str != null && !str.trim().equals("") &&
+ num <inputStrs.size()) {
+ if (str.contains("Route Distinguisher")) {
+ key.setLength(0);
+ key.append(BgpConstants.BGP_COUNTER_RD_ROUTE_COUNT).append(":").
+ append("BGP_RD_").append(rd).append("_route_count");
+ countersMap.put(key.toString(), Integer.toString(route_count));
+ return num - 1;
+ }
+ route_count++;
+ num++;
+ if (num == inputStrs.size()) {
+ break;
+ }
+ str = inputStrs.get(num);
+ }
+ if (route_count == 0) {
+ // Erroneous condition, should never happen.
+ // Implies that the file contains marker for RD without routes.
+ // will form an infinite loop if not broken
+ // by sending a big number back.
+ return ~0;
+ }
+ key.setLength(0);
+ key.append(BgpConstants.BGP_COUNTER_RD_ROUTE_COUNT).append(":").
+ append("BGP_RD_").append(rd).append("_route_count");
+ countersMap.put(key.toString(), Integer.toString(route_count));
+ return num - 1;
+ }
+
+ public void resetCounters() {
+ countersMap.clear();
+ resetFile("cmd_ip_bgp_summary.txt");
+ resetFile("cmd_bgp_ipv4_unicast_statistics.txt");
+ resetFile("cmd_ip_bgp_vpnv4_all.txt");
+ }
+
+ public void resetFile(String fileName) {
+ File fileHndl = (new File(fileName));
+ PrintWriter writer;
+ boolean success;
+
+ System.gc();
+ success = fileHndl.delete();
+ if (!success) {
+ try {
+ writer = new PrintWriter(fileHndl);
+ writer.print("");
+ writer.close();
+ } catch (Exception e) {
+ return;
+ }
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager.oam;
+
+import com.google.common.collect.ImmutableBiMap;
+import com.google.common.collect.ImmutableMap;
+
+import javax.management.MBeanNotificationInfo;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import java.util.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * Created by ECHIAPT on 9/25/2015.
+ */
+public class BgpCountersBroadcaster extends NotificationBroadcasterSupport implements BgpCountersBroadcasterMBean {
+ public Map<String, String> bgpCountersMap = new HashMap<String, String>();
+ private static final Logger LOGGER = LoggerFactory.getLogger(BgpCountersBroadcaster.class);
+
+ public Map<String, String> retrieveCounterMap() {
+ LOGGER.trace("Polled retrieveCounterMap");
+ Map<String, String> countersVal = new HashMap<String, String>(bgpCountersMap);
+ Iterator<Map.Entry<String, String>> entries = countersVal.entrySet().iterator();
+ while (entries.hasNext()) {
+ Map.Entry<String, String> entry = entries.next();
+ LOGGER.trace(entry.getKey() + ", Value from MBean= " + entry.getValue());
+ }
+ return countersVal;
+ }
+
+ public void setBgpCountersMap(Map fetchedCountersMap) {
+ LOGGER.trace("putAll");
+ bgpCountersMap.clear();
+ bgpCountersMap.putAll(fetchedCountersMap);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager.oam;
+
+ import java.util.ArrayList;
+ import java.util.Map;
+
+/**
+ * Created by echiapt on 9/28/2015.
+ */
+public interface BgpCountersBroadcasterMBean {
+ public Map retrieveCounterMap();
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager.thrift.client;
+
+import java.util.*;
+import org.apache.thrift.protocol.TBinaryProtocol;
+import org.apache.thrift.protocol.TProtocol;
+import org.apache.thrift.TException;
+import org.apache.thrift.transport.TSocket;
+import org.apache.thrift.transport.TTransport;
+import org.apache.thrift.transport.TTransportException;
+import org.opendaylight.bgpmanager.thrift.gen.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BgpRouter {
+ private static TTransport transport;
+ private static TProtocol protocol;
+ private static BgpConfigurator.Client bgpClient=null;
+ private static final Logger LOGGER = LoggerFactory.getLogger(BgpRouter.class);
+
+ private enum Optype {
+ START, STOP, NBR, VRF, PFX, SRC, MHOP, LOG, AF, GR
+ };
+
+ private final static int GET_RTS_INIT = 0;
+ private final static int GET_RTS_NEXT = 1;
+ private final static int CONNECTION_TIMEOUT = 2000;
+
+
+ private class BgpOp {
+ public Optype type;
+ public boolean add;
+ public String[] strs;
+ public int[] ints;
+ public List<String> irts;
+ public List<String> erts;
+ public static final int ignore = 0;
+ public BgpOp() {
+ strs = new String[3];
+ ints = new int[2];
+ }
+ }
+
+ private static BgpOp bop;
+
+ public synchronized void disconnect() {
+ bgpClient = null;
+ if (transport != null) {
+ transport.close();
+ }
+ }
+
+ public synchronized boolean connect(String bgpHost, int bgpPort) {
+ String msgPiece = "BGP config server at "+bgpHost+":"+bgpPort;
+
+ disconnect();
+ try {
+ TSocket ts = new TSocket(bgpHost, bgpPort, CONNECTION_TIMEOUT);
+ transport = ts;
+ transport.open();
+ ts.setTimeout(0);
+ } catch (TTransportException tte) {
+ LOGGER.error("Failed connecting to "+msgPiece+
+ "; Exception: "+tte);
+ return false;
+ }
+ protocol = new TBinaryProtocol(transport);
+ bgpClient = new BgpConfigurator.Client(protocol);
+ LOGGER.info("Connected to "+msgPiece);
+ return true;
+ }
+
+ private BgpRouter() {
+ bop = new BgpOp();
+ }
+
+ private static BgpRouter br = null;
+
+ public static synchronized BgpRouter getInstance() {
+ return (br == null ? br = new BgpRouter() : br);
+ }
+
+ private void dispatch(BgpOp op)
+ throws TException, BgpRouterException {
+ int result = 1;
+
+ if (bgpClient == null) {
+ throw new BgpRouterException(BgpRouterException.BGP_ERR_NOT_INITED);
+ }
+
+ switch (op.type) {
+ case START:
+ result = bgpClient.startBgp(op.ints[0], op.strs[0],
+ op.ignore, op.ignore, op.ignore, op.ints[1], op.add);
+ break;
+ case STOP:
+ result = bgpClient.stopBgp(op.ints[0]);
+ break;
+ case NBR:
+ result = bop.add ?
+ bgpClient.createPeer(op.strs[0], op.ints[0])
+ : bgpClient.deletePeer(op.strs[0]);
+ break;
+ case VRF:
+ result = bop.add ?
+ bgpClient.addVrf(op.strs[0], op.irts, op.erts)
+ : bgpClient.delVrf(op.strs[0]);
+ break;
+ case PFX:
+ // order of args is different in addPrefix(), hence the
+ // seeming out-of-order-ness of string indices
+ result = bop.add ?
+ bgpClient.pushRoute(op.strs[1], op.strs[2],
+ op.strs[0], op.ints[0])
+ : bgpClient.withdrawRoute(op.strs[1], op.strs[0]);
+ break;
+ case LOG:
+ result = bgpClient.setLogConfig(op.strs[0], op.strs[1]);
+ break;
+ case MHOP:
+ result = bop.add ?
+ bgpClient.setEbgpMultihop(op.strs[0], op.ints[0])
+ : bgpClient.unsetEbgpMultihop(op.strs[0]);
+ break;
+ case SRC:
+ result = bop.add ?
+ bgpClient.setUpdateSource(op.strs[0], op.strs[1])
+ : bgpClient.unsetUpdateSource(op.strs[0]);
+ break;
+ default: break;
+ case AF:
+ af_afi afi = af_afi.findByValue(op.ints[0]);
+ af_safi safi = af_safi.findByValue(op.ints[1]);
+ result = bop.add ?
+ bgpClient.enableAddressFamily(op.strs[0], afi, safi)
+ : bgpClient.disableAddressFamily(op.strs[0], afi, safi);
+ break;
+ case GR:
+ result = bop.add ?
+ bgpClient.enableGracefulRestart(op.ints[0])
+ : bgpClient.disableGracefulRestart();
+ break;
+ }
+ if (result != 0) {
+ throw new BgpRouterException(result);
+ }
+ }
+
+ public synchronized void startBgp(int asNum, String rtrId, int stalepathTime,
+ boolean announceFbit)
+ throws TException, BgpRouterException {
+ bop.type = Optype.START;
+ bop.add = announceFbit;
+ bop.ints[0] = asNum;
+ bop.ints[1] = stalepathTime;
+ bop.strs[0] = rtrId;
+ LOGGER.debug("Starting BGP with as number {} and router ID {} ", asNum, rtrId);
+ dispatch(bop);
+ }
+
+ public synchronized void stopBgp(int asNum)
+ throws TException, BgpRouterException {
+ bop.type = Optype.STOP;
+ bop.ints[0] = asNum;
+ LOGGER.debug("Stopping BGP with as number {}", asNum);
+ dispatch(bop);
+ }
+
+ public synchronized void addNeighbor(String nbrIp, int nbrAsNum)
+ throws TException, BgpRouterException {
+ bop.type = Optype.NBR;
+ bop.add = true;
+ bop.strs[0] = nbrIp;
+ bop.ints[0] = nbrAsNum;
+ LOGGER.debug("Adding BGP Neighbor {} with as number {} ", nbrIp, nbrAsNum);
+ dispatch(bop);
+ }
+
+ public synchronized void delNeighbor(String nbrIp)
+ throws TException, BgpRouterException {
+ bop.type = Optype.NBR;
+ bop.add = false;
+ bop.strs[0] = nbrIp;
+ LOGGER.debug("Deleting BGP Neighbor {} ", nbrIp);
+ dispatch(bop);
+ }
+
+ public synchronized void addVrf(String rd, List<String> irts, List<String> erts)
+ throws TException, BgpRouterException {
+ bop.type = Optype.VRF;
+ bop.add = true;
+ bop.strs[0] = rd;
+ bop.irts = irts;
+ bop.erts = erts;
+ LOGGER.debug("Adding BGP VRF rd: {} ", rd);
+ dispatch(bop);
+ }
+
+ public synchronized void delVrf(String rd)
+ throws TException, BgpRouterException {
+ bop.type = Optype.VRF;
+ bop.add = false;
+ bop.strs[0] = rd;
+ LOGGER.debug("Deleting BGP VRF rd: {} " + rd);
+ dispatch(bop);
+ }
+
+ // bit of a mess-up: the order of arguments is different in
+ // the Thrift RPC: prefix-nexthop-rd-label.
+
+ public synchronized void addPrefix(String rd, String prefix, String nexthop, int label)
+ throws TException, BgpRouterException {
+ bop.type = Optype.PFX;
+ bop.add = true;
+ bop.strs[0] = rd;
+ bop.strs[1] = prefix;
+ bop.strs[2] = nexthop;
+ bop.ints[0] = label;
+ LOGGER.debug("Adding BGP route - rd:{} prefix:{} nexthop:{} label:{} ", rd ,prefix, nexthop, label);
+ dispatch(bop);
+ }
+
+ public synchronized void delPrefix(String rd, String prefix)
+ throws TException, BgpRouterException {
+ bop.type = Optype.PFX;
+ bop.add = false;
+ bop.strs[0] = rd;
+ bop.strs[1] = prefix;
+ LOGGER.debug("Deleting BGP route - rd:{} prefix:{} ", rd, prefix);
+ dispatch(bop);
+ }
+
+ public int initRibSync(BgpSyncHandle handle)
+ throws TException, BgpRouterException {
+ if (bgpClient == null) {
+ throw new BgpRouterException(BgpRouterException.BGP_ERR_NOT_INITED);
+ }
+ if (handle.getState() == BgpSyncHandle.ITERATING) {
+ return BgpRouterException.BGP_ERR_IN_ITER;
+ }
+ handle.setState(BgpSyncHandle.INITED);
+ handle.setMore(1);
+ return 0;
+ }
+
+ public int endRibSync(BgpSyncHandle handle)
+ throws TException, BgpRouterException {
+ if (bgpClient == null) {
+ throw new BgpRouterException(BgpRouterException.BGP_ERR_NOT_INITED);
+ }
+ int state = handle.getState();
+ switch (state) {
+ case BgpSyncHandle.INITED:
+ case BgpSyncHandle.ITERATING:
+ handle.setState(BgpSyncHandle.ABORTED);
+ break;
+ case BgpSyncHandle.DONE:
+ break;
+ case BgpSyncHandle.NEVER_DONE:
+ return BgpRouterException.BGP_ERR_NOT_ITER;
+ default:
+ break;
+ }
+ return 0;
+ }
+
+ public Routes doRibSync(BgpSyncHandle handle)
+ throws TException, BgpRouterException {
+ if (bgpClient == null) {
+ throw new BgpRouterException(BgpRouterException.BGP_ERR_NOT_INITED);
+ }
+ int state = handle.getState();
+ if (state != BgpSyncHandle.INITED && state != BgpSyncHandle.ITERATING) {
+ Routes r = new Routes();
+ r.setErrcode(BgpRouterException.BGP_ERR_NOT_ITER);
+ return r;
+ }
+ int op = (state == BgpSyncHandle.INITED) ?
+ GET_RTS_INIT : GET_RTS_NEXT;
+ handle.setState(BgpSyncHandle.ITERATING);
+ int winSize = handle.getMaxCount()*handle.getRouteSize();
+ Routes outRoutes = bgpClient.getRoutes(op, winSize);
+ if (outRoutes.errcode != 0) {
+ return outRoutes;
+ }
+ handle.setMore(outRoutes.more);
+ if (outRoutes.more == 0) {
+ handle.setState(BgpSyncHandle.DONE);
+ }
+ return outRoutes;
+ }
+
+ public synchronized void setLogging(String fileName, String debugLevel)
+ throws TException, BgpRouterException {
+ bop.type = Optype.LOG;
+ bop.strs[0] = fileName;
+ bop.strs[1] = debugLevel;
+ LOGGER.debug("Setting Log file to BGP VRF rd: {} ", fileName, debugLevel);
+ dispatch(bop);
+ }
+
+ public synchronized void addEbgpMultihop(String nbrIp, int nhops)
+ throws TException, BgpRouterException {
+ bop.type = Optype.MHOP;
+ bop.add = true;
+ bop.strs[0] = nbrIp;
+ bop.ints[0] = nhops;
+ LOGGER.debug("ebgp-multihop set for peer {}, num hops = {}",
+ nbrIp, nhops);
+ dispatch(bop);
+ }
+
+ public synchronized void delEbgpMultihop(String nbrIp)
+ throws TException, BgpRouterException {
+ bop.type = Optype.MHOP;
+ bop.add = false;
+ bop.strs[0] = nbrIp;
+ LOGGER.debug("ebgp-multihop deleted for peer {}", nbrIp);
+ dispatch(bop);
+ }
+
+ public synchronized void addUpdateSource(String nbrIp, String srcIp)
+ throws TException, BgpRouterException {
+ bop.type = Optype.SRC;
+ bop.add = true;
+ bop.strs[0] = nbrIp;
+ bop.strs[1] = srcIp;
+ LOGGER.debug("update-source added for peer {}, src-ip = {}",
+ nbrIp, srcIp);
+ dispatch(bop);
+ }
+
+ public synchronized void delUpdateSource(String nbrIp)
+ throws TException, BgpRouterException {
+ bop.type = Optype.SRC;
+ bop.add = false;
+ bop.strs[0] = nbrIp;
+ LOGGER.debug("update-source deleted for peer {}", nbrIp);
+ dispatch(bop);
+ }
+
+ public synchronized void addAddressFamily(String nbrIp,
+ af_afi afi, af_safi safi)
+ throws TException, BgpRouterException {
+ bop.type = Optype.AF;
+ bop.add = true;
+ bop.strs[0] = nbrIp;
+ bop.ints[0] = afi.getValue();
+ bop.ints[1] = safi.getValue();
+ LOGGER.debug("addr family added for peer {}, afi = {}, safi = {}",
+ nbrIp, bop.ints[0], bop.ints[1]);
+ dispatch(bop);
+ }
+
+ public synchronized void delAddressFamily(String nbrIp,
+ af_afi afi, af_safi safi)
+ throws TException, BgpRouterException {
+ bop.type = Optype.AF;
+ bop.add = false;
+ bop.strs[0] = nbrIp;
+ bop.ints[0] = afi.getValue();
+ bop.ints[1] = safi.getValue();
+ LOGGER.debug("addr family deleted for peer {}, afi = {}, safi = {}",
+ nbrIp, bop.ints[0], bop.ints[1]);
+ dispatch(bop);
+ }
+
+ public synchronized void addGracefulRestart(int stalepathTime)
+ throws TException, BgpRouterException {
+ bop.type = Optype.GR;
+ bop.add = true;
+ bop.ints[0] = stalepathTime;
+ LOGGER.debug("graceful restart added, stale-path-time = {}",
+ stalepathTime);
+ dispatch(bop);
+ }
+
+ public synchronized void delGracefulRestart()
+ throws TException, BgpRouterException {
+ bop.type = Optype.GR;
+ bop.add = false;
+ LOGGER.debug("graceful restart deleted");
+ dispatch(bop);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager.thrift.client;
+
+import org.opendaylight.bgpmanager.thrift.gen.qbgpConstants;
+
+public class BgpRouterException extends Exception {
+ public final static int BGP_ERR_INITED = 101;
+ public final static int BGP_ERR_NOT_INITED = 102;
+ public final static int BGP_ERR_IN_ITER = 103;
+
+ // the following consts are server-dictated. do not modify
+ public final static int BGP_ERR_FAILED = qbgpConstants. BGP_ERR_FAILED;
+ public final static int BGP_ERR_ACTIVE = qbgpConstants.BGP_ERR_ACTIVE;
+ public final static int BGP_ERR_INACTIVE = qbgpConstants.BGP_ERR_INACTIVE;
+ public final static int BGP_ERR_NOT_ITER = qbgpConstants.BGP_ERR_NOT_ITER;
+ public final static int BGP_ERR_PARAM = qbgpConstants.BGP_ERR_PARAM;
+
+ private int errcode;
+
+ public BgpRouterException(int cause) {
+ errcode = cause;
+ }
+
+ public int getErrorCode() {
+ return errcode;
+ }
+
+ public String toString() {
+ String s = "("+errcode+") ";
+
+ switch (errcode) {
+ case BGP_ERR_INITED :
+ s += "Attempt to reinitialize BgpRouter thrift client";
+ break;
+ case BGP_ERR_NOT_INITED :
+ s += "BgpRouter thrift client was not initialized";
+ break;
+ case BGP_ERR_FAILED :
+ s += "Error reported by BGP, check qbgp.log";
+ break;
+ case BGP_ERR_ACTIVE :
+ s += "Attempt to start router instance when already active";
+ break;
+ case BGP_ERR_INACTIVE :
+ s += "Router instance is not active";
+ break;
+ case BGP_ERR_IN_ITER :
+ s += "Attempt to start route iteration when already "+
+ "in the middle of one";
+ break;
+ case BGP_ERR_NOT_ITER :
+ s += "Route iteration not initialized";
+ break;
+ case BGP_ERR_PARAM :
+ s += "Parameter validation or Unknown error";
+ break;
+ default :
+ s += "Unknown error";
+ break;
+ }
+ return s;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager.thrift.client;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.SocketException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BgpSyncHandle {
+ private static BgpSyncHandle handle = null;
+ private static final Logger LOGGER = LoggerFactory.getLogger(BgpSyncHandle.class);
+ private int more;
+ private int state;
+
+ public static final int INITED = 1;
+ public static final int ITERATING = 2;
+ public static final int DONE = 3;
+ public static final int ABORTED = 4;
+ public static final int NEVER_DONE = 5;
+
+ public static final int DEFAULT_TCP_SOCK_SZ = 87380; //default receive buffer size on linux > 2.4
+
+ private BgpSyncHandle() {
+ more = 1;
+ state = NEVER_DONE;
+ }
+
+ public static synchronized BgpSyncHandle getInstance() {
+ if (handle == null) {
+ handle = new BgpSyncHandle();
+ }
+ return handle;
+ }
+
+ public synchronized int getState() {
+ return state;
+ }
+
+ public int getMaxCount() {
+ //compute the max count of routes we would like to send
+ Socket skt = new Socket();
+ int sockBufSz = DEFAULT_TCP_SOCK_SZ;
+ try {
+ sockBufSz = skt.getReceiveBufferSize();
+ } catch (SocketException s) {
+ LOGGER.warn("Socket Exception while retrieving default socket buffer size");
+ }
+ try {
+ skt.close();
+ } catch (IOException e) {
+ LOGGER.warn("IO Exception while closing socket for retrieving default socket buffer size");
+ }
+ return sockBufSz/getRouteSize();
+ }
+
+ public int getRouteSize() {
+ //size of one update structure on the wire. ideally
+ //this should be computed; or thrift sure has a nice
+ //way to tell this to the applciation, but for the
+ //moment, we just use 8 bytes more than the size of
+ //the C struct.
+
+ return 96;
+ }
+
+ public int setState(int state) {
+ int retval = this.state;
+ this.state = state;
+ return retval;
+ }
+
+ public int setMore(int more) {
+ int retval = this.more;
+ this.more = more;
+ return retval;
+ }
+}
+
+
+
--- /dev/null
+/**
+ * Autogenerated by Thrift Compiler (0.9.1)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ * @generated
+ */
+
+package org.opendaylight.bgpmanager.thrift.gen;
+
+import org.apache.thrift.scheme.IScheme;
+import org.apache.thrift.scheme.SchemeFactory;
+import org.apache.thrift.scheme.StandardScheme;
+
+import org.apache.thrift.scheme.TupleScheme;
+import org.apache.thrift.protocol.TTupleProtocol;
+import org.apache.thrift.protocol.TProtocolException;
+import org.apache.thrift.EncodingUtils;
+import org.apache.thrift.TException;
+import org.apache.thrift.async.AsyncMethodCallback;
+import org.apache.thrift.server.AbstractNonblockingServer.*;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.EnumMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.EnumSet;
+import java.util.Collections;
+import java.util.BitSet;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BgpConfigurator {
+
+ public interface Iface {
+
+ public int startBgp(int asNumber, String routerId, int port, int holdTime, int keepAliveTime, int stalepathTime, boolean announceFbit) throws org.apache.thrift.TException;
+
+ public int stopBgp(int asNumber) throws org.apache.thrift.TException;
+
+ public int createPeer(String ipAddress, int asNumber) throws org.apache.thrift.TException;
+
+ public int deletePeer(String ipAddress) throws org.apache.thrift.TException;
+
+ public int addVrf(String rd, List<String> irts, List<String> erts) throws org.apache.thrift.TException;
+
+ public int delVrf(String rd) throws org.apache.thrift.TException;
+
+ public int pushRoute(String prefix, String nexthop, String rd, int label) throws org.apache.thrift.TException;
+
+ public int withdrawRoute(String prefix, String rd) throws org.apache.thrift.TException;
+
+ public int setEbgpMultihop(String peerIp, int nHops) throws org.apache.thrift.TException;
+
+ public int unsetEbgpMultihop(String peerIp) throws org.apache.thrift.TException;
+
+ public int setUpdateSource(String peerIp, String srcIp) throws org.apache.thrift.TException;
+
+ public int unsetUpdateSource(String peerIp) throws org.apache.thrift.TException;
+
+ public int enableAddressFamily(String peerIp, af_afi afi, af_safi safi) throws org.apache.thrift.TException;
+
+ public int disableAddressFamily(String peerIp, af_afi afi, af_safi safi) throws org.apache.thrift.TException;
+
+ public int setLogConfig(String logFileName, String logLevel) throws org.apache.thrift.TException;
+
+ public int enableGracefulRestart(int stalepathTime) throws org.apache.thrift.TException;
+
+ public int disableGracefulRestart() throws org.apache.thrift.TException;
+
+ public Routes getRoutes(int optype, int winSize) throws org.apache.thrift.TException;
+
+ }
+
+ public interface AsyncIface {
+
+ public void startBgp(int asNumber, String routerId, int port, int holdTime, int keepAliveTime, int stalepathTime, boolean announceFbit, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ public void stopBgp(int asNumber, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ public void createPeer(String ipAddress, int asNumber, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ public void deletePeer(String ipAddress, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ public void addVrf(String rd, List<String> irts, List<String> erts, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ public void delVrf(String rd, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ public void pushRoute(String prefix, String nexthop, String rd, int label, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ public void withdrawRoute(String prefix, String rd, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ public void setEbgpMultihop(String peerIp, int nHops, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ public void unsetEbgpMultihop(String peerIp, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ public void setUpdateSource(String peerIp, String srcIp, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ public void unsetUpdateSource(String peerIp, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ public void enableAddressFamily(String peerIp, af_afi afi, af_safi safi, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ public void disableAddressFamily(String peerIp, af_afi afi, af_safi safi, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ public void setLogConfig(String logFileName, String logLevel, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ public void enableGracefulRestart(int stalepathTime, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ public void disableGracefulRestart(org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ public void getRoutes(int optype, int winSize, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ }
+
+ public static class Client extends org.apache.thrift.TServiceClient implements Iface {
+ public static class Factory implements org.apache.thrift.TServiceClientFactory<Client> {
+ public Factory() {}
+ public Client getClient(org.apache.thrift.protocol.TProtocol prot) {
+ return new Client(prot);
+ }
+ public Client getClient(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
+ return new Client(iprot, oprot);
+ }
+ }
+
+ public Client(org.apache.thrift.protocol.TProtocol prot)
+ {
+ super(prot, prot);
+ }
+
+ public Client(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
+ super(iprot, oprot);
+ }
+
+ public int startBgp(int asNumber, String routerId, int port, int holdTime, int keepAliveTime, int stalepathTime, boolean announceFbit) throws org.apache.thrift.TException
+ {
+ send_startBgp(asNumber, routerId, port, holdTime, keepAliveTime, stalepathTime, announceFbit);
+ return recv_startBgp();
+ }
+
+ public void send_startBgp(int asNumber, String routerId, int port, int holdTime, int keepAliveTime, int stalepathTime, boolean announceFbit) throws org.apache.thrift.TException
+ {
+ startBgp_args args = new startBgp_args();
+ args.setAsNumber(asNumber);
+ args.setRouterId(routerId);
+ args.setPort(port);
+ args.setHoldTime(holdTime);
+ args.setKeepAliveTime(keepAliveTime);
+ args.setStalepathTime(stalepathTime);
+ args.setAnnounceFbit(announceFbit);
+ sendBase("startBgp", args);
+ }
+
+ public int recv_startBgp() throws org.apache.thrift.TException
+ {
+ startBgp_result result = new startBgp_result();
+ receiveBase(result, "startBgp");
+ if (result.isSetSuccess()) {
+ return result.success;
+ }
+ throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "startBgp failed: unknown result");
+ }
+
+ public int stopBgp(int asNumber) throws org.apache.thrift.TException
+ {
+ send_stopBgp(asNumber);
+ return recv_stopBgp();
+ }
+
+ public void send_stopBgp(int asNumber) throws org.apache.thrift.TException
+ {
+ stopBgp_args args = new stopBgp_args();
+ args.setAsNumber(asNumber);
+ sendBase("stopBgp", args);
+ }
+
+ public int recv_stopBgp() throws org.apache.thrift.TException
+ {
+ stopBgp_result result = new stopBgp_result();
+ receiveBase(result, "stopBgp");
+ if (result.isSetSuccess()) {
+ return result.success;
+ }
+ throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "stopBgp failed: unknown result");
+ }
+
+ public int createPeer(String ipAddress, int asNumber) throws org.apache.thrift.TException
+ {
+ send_createPeer(ipAddress, asNumber);
+ return recv_createPeer();
+ }
+
+ public void send_createPeer(String ipAddress, int asNumber) throws org.apache.thrift.TException
+ {
+ createPeer_args args = new createPeer_args();
+ args.setIpAddress(ipAddress);
+ args.setAsNumber(asNumber);
+ sendBase("createPeer", args);
+ }
+
+ public int recv_createPeer() throws org.apache.thrift.TException
+ {
+ createPeer_result result = new createPeer_result();
+ receiveBase(result, "createPeer");
+ if (result.isSetSuccess()) {
+ return result.success;
+ }
+ throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "createPeer failed: unknown result");
+ }
+
+ public int deletePeer(String ipAddress) throws org.apache.thrift.TException
+ {
+ send_deletePeer(ipAddress);
+ return recv_deletePeer();
+ }
+
+ public void send_deletePeer(String ipAddress) throws org.apache.thrift.TException
+ {
+ deletePeer_args args = new deletePeer_args();
+ args.setIpAddress(ipAddress);
+ sendBase("deletePeer", args);
+ }
+
+ public int recv_deletePeer() throws org.apache.thrift.TException
+ {
+ deletePeer_result result = new deletePeer_result();
+ receiveBase(result, "deletePeer");
+ if (result.isSetSuccess()) {
+ return result.success;
+ }
+ throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "deletePeer failed: unknown result");
+ }
+
+ public int addVrf(String rd, List<String> irts, List<String> erts) throws org.apache.thrift.TException
+ {
+ send_addVrf(rd, irts, erts);
+ return recv_addVrf();
+ }
+
+ public void send_addVrf(String rd, List<String> irts, List<String> erts) throws org.apache.thrift.TException
+ {
+ addVrf_args args = new addVrf_args();
+ args.setRd(rd);
+ args.setIrts(irts);
+ args.setErts(erts);
+ sendBase("addVrf", args);
+ }
+
+ public int recv_addVrf() throws org.apache.thrift.TException
+ {
+ addVrf_result result = new addVrf_result();
+ receiveBase(result, "addVrf");
+ if (result.isSetSuccess()) {
+ return result.success;
+ }
+ throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "addVrf failed: unknown result");
+ }
+
+ public int delVrf(String rd) throws org.apache.thrift.TException
+ {
+ send_delVrf(rd);
+ return recv_delVrf();
+ }
+
+ public void send_delVrf(String rd) throws org.apache.thrift.TException
+ {
+ delVrf_args args = new delVrf_args();
+ args.setRd(rd);
+ sendBase("delVrf", args);
+ }
+
+ public int recv_delVrf() throws org.apache.thrift.TException
+ {
+ delVrf_result result = new delVrf_result();
+ receiveBase(result, "delVrf");
+ if (result.isSetSuccess()) {
+ return result.success;
+ }
+ throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "delVrf failed: unknown result");
+ }
+
+ public int pushRoute(String prefix, String nexthop, String rd, int label) throws org.apache.thrift.TException
+ {
+ send_pushRoute(prefix, nexthop, rd, label);
+ return recv_pushRoute();
+ }
+
+ public void send_pushRoute(String prefix, String nexthop, String rd, int label) throws org.apache.thrift.TException
+ {
+ pushRoute_args args = new pushRoute_args();
+ args.setPrefix(prefix);
+ args.setNexthop(nexthop);
+ args.setRd(rd);
+ args.setLabel(label);
+ sendBase("pushRoute", args);
+ }
+
+ public int recv_pushRoute() throws org.apache.thrift.TException
+ {
+ pushRoute_result result = new pushRoute_result();
+ receiveBase(result, "pushRoute");
+ if (result.isSetSuccess()) {
+ return result.success;
+ }
+ throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "pushRoute failed: unknown result");
+ }
+
+ public int withdrawRoute(String prefix, String rd) throws org.apache.thrift.TException
+ {
+ send_withdrawRoute(prefix, rd);
+ return recv_withdrawRoute();
+ }
+
+ public void send_withdrawRoute(String prefix, String rd) throws org.apache.thrift.TException
+ {
+ withdrawRoute_args args = new withdrawRoute_args();
+ args.setPrefix(prefix);
+ args.setRd(rd);
+ sendBase("withdrawRoute", args);
+ }
+
+ public int recv_withdrawRoute() throws org.apache.thrift.TException
+ {
+ withdrawRoute_result result = new withdrawRoute_result();
+ receiveBase(result, "withdrawRoute");
+ if (result.isSetSuccess()) {
+ return result.success;
+ }
+ throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "withdrawRoute failed: unknown result");
+ }
+
+ public int setEbgpMultihop(String peerIp, int nHops) throws org.apache.thrift.TException
+ {
+ send_setEbgpMultihop(peerIp, nHops);
+ return recv_setEbgpMultihop();
+ }
+
+ public void send_setEbgpMultihop(String peerIp, int nHops) throws org.apache.thrift.TException
+ {
+ setEbgpMultihop_args args = new setEbgpMultihop_args();
+ args.setPeerIp(peerIp);
+ args.setNHops(nHops);
+ sendBase("setEbgpMultihop", args);
+ }
+
+ public int recv_setEbgpMultihop() throws org.apache.thrift.TException
+ {
+ setEbgpMultihop_result result = new setEbgpMultihop_result();
+ receiveBase(result, "setEbgpMultihop");
+ if (result.isSetSuccess()) {
+ return result.success;
+ }
+ throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "setEbgpMultihop failed: unknown result");
+ }
+
+ public int unsetEbgpMultihop(String peerIp) throws org.apache.thrift.TException
+ {
+ send_unsetEbgpMultihop(peerIp);
+ return recv_unsetEbgpMultihop();
+ }
+
+ public void send_unsetEbgpMultihop(String peerIp) throws org.apache.thrift.TException
+ {
+ unsetEbgpMultihop_args args = new unsetEbgpMultihop_args();
+ args.setPeerIp(peerIp);
+ sendBase("unsetEbgpMultihop", args);
+ }
+
+ public int recv_unsetEbgpMultihop() throws org.apache.thrift.TException
+ {
+ unsetEbgpMultihop_result result = new unsetEbgpMultihop_result();
+ receiveBase(result, "unsetEbgpMultihop");
+ if (result.isSetSuccess()) {
+ return result.success;
+ }
+ throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "unsetEbgpMultihop failed: unknown result");
+ }
+
+ public int setUpdateSource(String peerIp, String srcIp) throws org.apache.thrift.TException
+ {
+ send_setUpdateSource(peerIp, srcIp);
+ return recv_setUpdateSource();
+ }
+
+ public void send_setUpdateSource(String peerIp, String srcIp) throws org.apache.thrift.TException
+ {
+ setUpdateSource_args args = new setUpdateSource_args();
+ args.setPeerIp(peerIp);
+ args.setSrcIp(srcIp);
+ sendBase("setUpdateSource", args);
+ }
+
+ public int recv_setUpdateSource() throws org.apache.thrift.TException
+ {
+ setUpdateSource_result result = new setUpdateSource_result();
+ receiveBase(result, "setUpdateSource");
+ if (result.isSetSuccess()) {
+ return result.success;
+ }
+ throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "setUpdateSource failed: unknown result");
+ }
+
+ public int unsetUpdateSource(String peerIp) throws org.apache.thrift.TException
+ {
+ send_unsetUpdateSource(peerIp);
+ return recv_unsetUpdateSource();
+ }
+
+ public void send_unsetUpdateSource(String peerIp) throws org.apache.thrift.TException
+ {
+ unsetUpdateSource_args args = new unsetUpdateSource_args();
+ args.setPeerIp(peerIp);
+ sendBase("unsetUpdateSource", args);
+ }
+
+ public int recv_unsetUpdateSource() throws org.apache.thrift.TException
+ {
+ unsetUpdateSource_result result = new unsetUpdateSource_result();
+ receiveBase(result, "unsetUpdateSource");
+ if (result.isSetSuccess()) {
+ return result.success;
+ }
+ throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "unsetUpdateSource failed: unknown result");
+ }
+
+ public int enableAddressFamily(String peerIp, af_afi afi, af_safi safi) throws org.apache.thrift.TException
+ {
+ send_enableAddressFamily(peerIp, afi, safi);
+ return recv_enableAddressFamily();
+ }
+
+ public void send_enableAddressFamily(String peerIp, af_afi afi, af_safi safi) throws org.apache.thrift.TException
+ {
+ enableAddressFamily_args args = new enableAddressFamily_args();
+ args.setPeerIp(peerIp);
+ args.setAfi(afi);
+ args.setSafi(safi);
+ sendBase("enableAddressFamily", args);
+ }
+
+ public int recv_enableAddressFamily() throws org.apache.thrift.TException
+ {
+ enableAddressFamily_result result = new enableAddressFamily_result();
+ receiveBase(result, "enableAddressFamily");
+ if (result.isSetSuccess()) {
+ return result.success;
+ }
+ throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "enableAddressFamily failed: unknown result");
+ }
+
+ public int disableAddressFamily(String peerIp, af_afi afi, af_safi safi) throws org.apache.thrift.TException
+ {
+ send_disableAddressFamily(peerIp, afi, safi);
+ return recv_disableAddressFamily();
+ }
+
+ public void send_disableAddressFamily(String peerIp, af_afi afi, af_safi safi) throws org.apache.thrift.TException
+ {
+ disableAddressFamily_args args = new disableAddressFamily_args();
+ args.setPeerIp(peerIp);
+ args.setAfi(afi);
+ args.setSafi(safi);
+ sendBase("disableAddressFamily", args);
+ }
+
+ public int recv_disableAddressFamily() throws org.apache.thrift.TException
+ {
+ disableAddressFamily_result result = new disableAddressFamily_result();
+ receiveBase(result, "disableAddressFamily");
+ if (result.isSetSuccess()) {
+ return result.success;
+ }
+ throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "disableAddressFamily failed: unknown result");
+ }
+
+ public int setLogConfig(String logFileName, String logLevel) throws org.apache.thrift.TException
+ {
+ send_setLogConfig(logFileName, logLevel);
+ return recv_setLogConfig();
+ }
+
+ public void send_setLogConfig(String logFileName, String logLevel) throws org.apache.thrift.TException
+ {
+ setLogConfig_args args = new setLogConfig_args();
+ args.setLogFileName(logFileName);
+ args.setLogLevel(logLevel);
+ sendBase("setLogConfig", args);
+ }
+
+ public int recv_setLogConfig() throws org.apache.thrift.TException
+ {
+ setLogConfig_result result = new setLogConfig_result();
+ receiveBase(result, "setLogConfig");
+ if (result.isSetSuccess()) {
+ return result.success;
+ }
+ throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "setLogConfig failed: unknown result");
+ }
+
+ public int enableGracefulRestart(int stalepathTime) throws org.apache.thrift.TException
+ {
+ send_enableGracefulRestart(stalepathTime);
+ return recv_enableGracefulRestart();
+ }
+
+ public void send_enableGracefulRestart(int stalepathTime) throws org.apache.thrift.TException
+ {
+ enableGracefulRestart_args args = new enableGracefulRestart_args();
+ args.setStalepathTime(stalepathTime);
+ sendBase("enableGracefulRestart", args);
+ }
+
+ public int recv_enableGracefulRestart() throws org.apache.thrift.TException
+ {
+ enableGracefulRestart_result result = new enableGracefulRestart_result();
+ receiveBase(result, "enableGracefulRestart");
+ if (result.isSetSuccess()) {
+ return result.success;
+ }
+ throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "enableGracefulRestart failed: unknown result");
+ }
+
+ public int disableGracefulRestart() throws org.apache.thrift.TException
+ {
+ send_disableGracefulRestart();
+ return recv_disableGracefulRestart();
+ }
+
+ public void send_disableGracefulRestart() throws org.apache.thrift.TException
+ {
+ disableGracefulRestart_args args = new disableGracefulRestart_args();
+ sendBase("disableGracefulRestart", args);
+ }
+
+ public int recv_disableGracefulRestart() throws org.apache.thrift.TException
+ {
+ disableGracefulRestart_result result = new disableGracefulRestart_result();
+ receiveBase(result, "disableGracefulRestart");
+ if (result.isSetSuccess()) {
+ return result.success;
+ }
+ throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "disableGracefulRestart failed: unknown result");
+ }
+
+ public Routes getRoutes(int optype, int winSize) throws org.apache.thrift.TException
+ {
+ send_getRoutes(optype, winSize);
+ return recv_getRoutes();
+ }
+
+ public void send_getRoutes(int optype, int winSize) throws org.apache.thrift.TException
+ {
+ getRoutes_args args = new getRoutes_args();
+ args.setOptype(optype);
+ args.setWinSize(winSize);
+ sendBase("getRoutes", args);
+ }
+
+ public Routes recv_getRoutes() throws org.apache.thrift.TException
+ {
+ getRoutes_result result = new getRoutes_result();
+ receiveBase(result, "getRoutes");
+ if (result.isSetSuccess()) {
+ return result.success;
+ }
+ throw new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.MISSING_RESULT, "getRoutes failed: unknown result");
+ }
+
+ }
+ public static class AsyncClient extends org.apache.thrift.async.TAsyncClient implements AsyncIface {
+ public static class Factory implements org.apache.thrift.async.TAsyncClientFactory<AsyncClient> {
+ private org.apache.thrift.async.TAsyncClientManager clientManager;
+ private org.apache.thrift.protocol.TProtocolFactory protocolFactory;
+ public Factory(org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.protocol.TProtocolFactory protocolFactory) {
+ this.clientManager = clientManager;
+ this.protocolFactory = protocolFactory;
+ }
+ public AsyncClient getAsyncClient(org.apache.thrift.transport.TNonblockingTransport transport) {
+ return new AsyncClient(protocolFactory, clientManager, transport);
+ }
+ }
+
+ public AsyncClient(org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.transport.TNonblockingTransport transport) {
+ super(protocolFactory, clientManager, transport);
+ }
+
+ public void startBgp(int asNumber, String routerId, int port, int holdTime, int keepAliveTime, int stalepathTime, boolean announceFbit, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ startBgp_call method_call = new startBgp_call(asNumber, routerId, port, holdTime, keepAliveTime, stalepathTime, announceFbit, resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class startBgp_call extends org.apache.thrift.async.TAsyncMethodCall {
+ private int asNumber;
+ private String routerId;
+ private int port;
+ private int holdTime;
+ private int keepAliveTime;
+ private int stalepathTime;
+ private boolean announceFbit;
+ public startBgp_call(int asNumber, String routerId, int port, int holdTime, int keepAliveTime, int stalepathTime, boolean announceFbit, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, false);
+ this.asNumber = asNumber;
+ this.routerId = routerId;
+ this.port = port;
+ this.holdTime = holdTime;
+ this.keepAliveTime = keepAliveTime;
+ this.stalepathTime = stalepathTime;
+ this.announceFbit = announceFbit;
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("startBgp", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ startBgp_args args = new startBgp_args();
+ args.setAsNumber(asNumber);
+ args.setRouterId(routerId);
+ args.setPort(port);
+ args.setHoldTime(holdTime);
+ args.setKeepAliveTime(keepAliveTime);
+ args.setStalepathTime(stalepathTime);
+ args.setAnnounceFbit(announceFbit);
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public int getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ return (new Client(prot)).recv_startBgp();
+ }
+ }
+
+ public void stopBgp(int asNumber, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ stopBgp_call method_call = new stopBgp_call(asNumber, resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class stopBgp_call extends org.apache.thrift.async.TAsyncMethodCall {
+ private int asNumber;
+ public stopBgp_call(int asNumber, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, false);
+ this.asNumber = asNumber;
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("stopBgp", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ stopBgp_args args = new stopBgp_args();
+ args.setAsNumber(asNumber);
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public int getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ return (new Client(prot)).recv_stopBgp();
+ }
+ }
+
+ public void createPeer(String ipAddress, int asNumber, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ createPeer_call method_call = new createPeer_call(ipAddress, asNumber, resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class createPeer_call extends org.apache.thrift.async.TAsyncMethodCall {
+ private String ipAddress;
+ private int asNumber;
+ public createPeer_call(String ipAddress, int asNumber, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, false);
+ this.ipAddress = ipAddress;
+ this.asNumber = asNumber;
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("createPeer", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ createPeer_args args = new createPeer_args();
+ args.setIpAddress(ipAddress);
+ args.setAsNumber(asNumber);
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public int getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ return (new Client(prot)).recv_createPeer();
+ }
+ }
+
+ public void deletePeer(String ipAddress, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ deletePeer_call method_call = new deletePeer_call(ipAddress, resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class deletePeer_call extends org.apache.thrift.async.TAsyncMethodCall {
+ private String ipAddress;
+ public deletePeer_call(String ipAddress, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, false);
+ this.ipAddress = ipAddress;
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("deletePeer", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ deletePeer_args args = new deletePeer_args();
+ args.setIpAddress(ipAddress);
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public int getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ return (new Client(prot)).recv_deletePeer();
+ }
+ }
+
+ public void addVrf(String rd, List<String> irts, List<String> erts, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ addVrf_call method_call = new addVrf_call(rd, irts, erts, resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class addVrf_call extends org.apache.thrift.async.TAsyncMethodCall {
+ private String rd;
+ private List<String> irts;
+ private List<String> erts;
+ public addVrf_call(String rd, List<String> irts, List<String> erts, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, false);
+ this.rd = rd;
+ this.irts = irts;
+ this.erts = erts;
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("addVrf", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ addVrf_args args = new addVrf_args();
+ args.setRd(rd);
+ args.setIrts(irts);
+ args.setErts(erts);
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public int getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ return (new Client(prot)).recv_addVrf();
+ }
+ }
+
+ public void delVrf(String rd, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ delVrf_call method_call = new delVrf_call(rd, resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class delVrf_call extends org.apache.thrift.async.TAsyncMethodCall {
+ private String rd;
+ public delVrf_call(String rd, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, false);
+ this.rd = rd;
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("delVrf", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ delVrf_args args = new delVrf_args();
+ args.setRd(rd);
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public int getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ return (new Client(prot)).recv_delVrf();
+ }
+ }
+
+ public void pushRoute(String prefix, String nexthop, String rd, int label, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ pushRoute_call method_call = new pushRoute_call(prefix, nexthop, rd, label, resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class pushRoute_call extends org.apache.thrift.async.TAsyncMethodCall {
+ private String prefix;
+ private String nexthop;
+ private String rd;
+ private int label;
+ public pushRoute_call(String prefix, String nexthop, String rd, int label, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, false);
+ this.prefix = prefix;
+ this.nexthop = nexthop;
+ this.rd = rd;
+ this.label = label;
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("pushRoute", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ pushRoute_args args = new pushRoute_args();
+ args.setPrefix(prefix);
+ args.setNexthop(nexthop);
+ args.setRd(rd);
+ args.setLabel(label);
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public int getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ return (new Client(prot)).recv_pushRoute();
+ }
+ }
+
+ public void withdrawRoute(String prefix, String rd, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ withdrawRoute_call method_call = new withdrawRoute_call(prefix, rd, resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class withdrawRoute_call extends org.apache.thrift.async.TAsyncMethodCall {
+ private String prefix;
+ private String rd;
+ public withdrawRoute_call(String prefix, String rd, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, false);
+ this.prefix = prefix;
+ this.rd = rd;
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("withdrawRoute", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ withdrawRoute_args args = new withdrawRoute_args();
+ args.setPrefix(prefix);
+ args.setRd(rd);
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public int getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ return (new Client(prot)).recv_withdrawRoute();
+ }
+ }
+
+ public void setEbgpMultihop(String peerIp, int nHops, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ setEbgpMultihop_call method_call = new setEbgpMultihop_call(peerIp, nHops, resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class setEbgpMultihop_call extends org.apache.thrift.async.TAsyncMethodCall {
+ private String peerIp;
+ private int nHops;
+ public setEbgpMultihop_call(String peerIp, int nHops, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, false);
+ this.peerIp = peerIp;
+ this.nHops = nHops;
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("setEbgpMultihop", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ setEbgpMultihop_args args = new setEbgpMultihop_args();
+ args.setPeerIp(peerIp);
+ args.setNHops(nHops);
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public int getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ return (new Client(prot)).recv_setEbgpMultihop();
+ }
+ }
+
+ public void unsetEbgpMultihop(String peerIp, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ unsetEbgpMultihop_call method_call = new unsetEbgpMultihop_call(peerIp, resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class unsetEbgpMultihop_call extends org.apache.thrift.async.TAsyncMethodCall {
+ private String peerIp;
+ public unsetEbgpMultihop_call(String peerIp, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, false);
+ this.peerIp = peerIp;
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("unsetEbgpMultihop", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ unsetEbgpMultihop_args args = new unsetEbgpMultihop_args();
+ args.setPeerIp(peerIp);
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public int getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ return (new Client(prot)).recv_unsetEbgpMultihop();
+ }
+ }
+
+ public void setUpdateSource(String peerIp, String srcIp, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ setUpdateSource_call method_call = new setUpdateSource_call(peerIp, srcIp, resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class setUpdateSource_call extends org.apache.thrift.async.TAsyncMethodCall {
+ private String peerIp;
+ private String srcIp;
+ public setUpdateSource_call(String peerIp, String srcIp, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, false);
+ this.peerIp = peerIp;
+ this.srcIp = srcIp;
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("setUpdateSource", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ setUpdateSource_args args = new setUpdateSource_args();
+ args.setPeerIp(peerIp);
+ args.setSrcIp(srcIp);
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public int getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ return (new Client(prot)).recv_setUpdateSource();
+ }
+ }
+
+ public void unsetUpdateSource(String peerIp, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ unsetUpdateSource_call method_call = new unsetUpdateSource_call(peerIp, resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class unsetUpdateSource_call extends org.apache.thrift.async.TAsyncMethodCall {
+ private String peerIp;
+ public unsetUpdateSource_call(String peerIp, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, false);
+ this.peerIp = peerIp;
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("unsetUpdateSource", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ unsetUpdateSource_args args = new unsetUpdateSource_args();
+ args.setPeerIp(peerIp);
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public int getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ return (new Client(prot)).recv_unsetUpdateSource();
+ }
+ }
+
+ public void enableAddressFamily(String peerIp, af_afi afi, af_safi safi, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ enableAddressFamily_call method_call = new enableAddressFamily_call(peerIp, afi, safi, resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class enableAddressFamily_call extends org.apache.thrift.async.TAsyncMethodCall {
+ private String peerIp;
+ private af_afi afi;
+ private af_safi safi;
+ public enableAddressFamily_call(String peerIp, af_afi afi, af_safi safi, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, false);
+ this.peerIp = peerIp;
+ this.afi = afi;
+ this.safi = safi;
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("enableAddressFamily", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ enableAddressFamily_args args = new enableAddressFamily_args();
+ args.setPeerIp(peerIp);
+ args.setAfi(afi);
+ args.setSafi(safi);
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public int getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ return (new Client(prot)).recv_enableAddressFamily();
+ }
+ }
+
+ public void disableAddressFamily(String peerIp, af_afi afi, af_safi safi, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ disableAddressFamily_call method_call = new disableAddressFamily_call(peerIp, afi, safi, resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class disableAddressFamily_call extends org.apache.thrift.async.TAsyncMethodCall {
+ private String peerIp;
+ private af_afi afi;
+ private af_safi safi;
+ public disableAddressFamily_call(String peerIp, af_afi afi, af_safi safi, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, false);
+ this.peerIp = peerIp;
+ this.afi = afi;
+ this.safi = safi;
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("disableAddressFamily", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ disableAddressFamily_args args = new disableAddressFamily_args();
+ args.setPeerIp(peerIp);
+ args.setAfi(afi);
+ args.setSafi(safi);
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public int getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ return (new Client(prot)).recv_disableAddressFamily();
+ }
+ }
+
+ public void setLogConfig(String logFileName, String logLevel, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ setLogConfig_call method_call = new setLogConfig_call(logFileName, logLevel, resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class setLogConfig_call extends org.apache.thrift.async.TAsyncMethodCall {
+ private String logFileName;
+ private String logLevel;
+ public setLogConfig_call(String logFileName, String logLevel, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, false);
+ this.logFileName = logFileName;
+ this.logLevel = logLevel;
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("setLogConfig", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ setLogConfig_args args = new setLogConfig_args();
+ args.setLogFileName(logFileName);
+ args.setLogLevel(logLevel);
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public int getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ return (new Client(prot)).recv_setLogConfig();
+ }
+ }
+
+ public void enableGracefulRestart(int stalepathTime, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ enableGracefulRestart_call method_call = new enableGracefulRestart_call(stalepathTime, resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class enableGracefulRestart_call extends org.apache.thrift.async.TAsyncMethodCall {
+ private int stalepathTime;
+ public enableGracefulRestart_call(int stalepathTime, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, false);
+ this.stalepathTime = stalepathTime;
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("enableGracefulRestart", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ enableGracefulRestart_args args = new enableGracefulRestart_args();
+ args.setStalepathTime(stalepathTime);
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public int getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ return (new Client(prot)).recv_enableGracefulRestart();
+ }
+ }
+
+ public void disableGracefulRestart(org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ disableGracefulRestart_call method_call = new disableGracefulRestart_call(resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class disableGracefulRestart_call extends org.apache.thrift.async.TAsyncMethodCall {
+ public disableGracefulRestart_call(org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, false);
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("disableGracefulRestart", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ disableGracefulRestart_args args = new disableGracefulRestart_args();
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public int getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ return (new Client(prot)).recv_disableGracefulRestart();
+ }
+ }
+
+ public void getRoutes(int optype, int winSize, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ getRoutes_call method_call = new getRoutes_call(optype, winSize, resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class getRoutes_call extends org.apache.thrift.async.TAsyncMethodCall {
+ private int optype;
+ private int winSize;
+ public getRoutes_call(int optype, int winSize, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, false);
+ this.optype = optype;
+ this.winSize = winSize;
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("getRoutes", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ getRoutes_args args = new getRoutes_args();
+ args.setOptype(optype);
+ args.setWinSize(winSize);
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public Routes getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ return (new Client(prot)).recv_getRoutes();
+ }
+ }
+
+ }
+
+ public static class Processor<I extends Iface> extends org.apache.thrift.TBaseProcessor<I> implements org.apache.thrift.TProcessor {
+ private static final Logger LOGGER = LoggerFactory.getLogger(Processor.class.getName());
+ public Processor(I iface) {
+ super(iface, getProcessMap(new HashMap<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>>()));
+ }
+
+ protected Processor(I iface, Map<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>> processMap) {
+ super(iface, getProcessMap(processMap));
+ }
+
+ private static <I extends Iface> Map<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>> getProcessMap(Map<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>> processMap) {
+ processMap.put("startBgp", new startBgp());
+ processMap.put("stopBgp", new stopBgp());
+ processMap.put("createPeer", new createPeer());
+ processMap.put("deletePeer", new deletePeer());
+ processMap.put("addVrf", new addVrf());
+ processMap.put("delVrf", new delVrf());
+ processMap.put("pushRoute", new pushRoute());
+ processMap.put("withdrawRoute", new withdrawRoute());
+ processMap.put("setEbgpMultihop", new setEbgpMultihop());
+ processMap.put("unsetEbgpMultihop", new unsetEbgpMultihop());
+ processMap.put("setUpdateSource", new setUpdateSource());
+ processMap.put("unsetUpdateSource", new unsetUpdateSource());
+ processMap.put("enableAddressFamily", new enableAddressFamily());
+ processMap.put("disableAddressFamily", new disableAddressFamily());
+ processMap.put("setLogConfig", new setLogConfig());
+ processMap.put("enableGracefulRestart", new enableGracefulRestart());
+ processMap.put("disableGracefulRestart", new disableGracefulRestart());
+ processMap.put("getRoutes", new getRoutes());
+ return processMap;
+ }
+
+ public static class startBgp<I extends Iface> extends org.apache.thrift.ProcessFunction<I, startBgp_args> {
+ public startBgp() {
+ super("startBgp");
+ }
+
+ public startBgp_args getEmptyArgsInstance() {
+ return new startBgp_args();
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public startBgp_result getResult(I iface, startBgp_args args) throws org.apache.thrift.TException {
+ startBgp_result result = new startBgp_result();
+ result.success = iface.startBgp(args.asNumber, args.routerId, args.port, args.holdTime, args.keepAliveTime, args.stalepathTime, args.announceFbit);
+ result.setSuccessIsSet(true);
+ return result;
+ }
+ }
+
+ public static class stopBgp<I extends Iface> extends org.apache.thrift.ProcessFunction<I, stopBgp_args> {
+ public stopBgp() {
+ super("stopBgp");
+ }
+
+ public stopBgp_args getEmptyArgsInstance() {
+ return new stopBgp_args();
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public stopBgp_result getResult(I iface, stopBgp_args args) throws org.apache.thrift.TException {
+ stopBgp_result result = new stopBgp_result();
+ result.success = iface.stopBgp(args.asNumber);
+ result.setSuccessIsSet(true);
+ return result;
+ }
+ }
+
+ public static class createPeer<I extends Iface> extends org.apache.thrift.ProcessFunction<I, createPeer_args> {
+ public createPeer() {
+ super("createPeer");
+ }
+
+ public createPeer_args getEmptyArgsInstance() {
+ return new createPeer_args();
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public createPeer_result getResult(I iface, createPeer_args args) throws org.apache.thrift.TException {
+ createPeer_result result = new createPeer_result();
+ result.success = iface.createPeer(args.ipAddress, args.asNumber);
+ result.setSuccessIsSet(true);
+ return result;
+ }
+ }
+
+ public static class deletePeer<I extends Iface> extends org.apache.thrift.ProcessFunction<I, deletePeer_args> {
+ public deletePeer() {
+ super("deletePeer");
+ }
+
+ public deletePeer_args getEmptyArgsInstance() {
+ return new deletePeer_args();
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public deletePeer_result getResult(I iface, deletePeer_args args) throws org.apache.thrift.TException {
+ deletePeer_result result = new deletePeer_result();
+ result.success = iface.deletePeer(args.ipAddress);
+ result.setSuccessIsSet(true);
+ return result;
+ }
+ }
+
+ public static class addVrf<I extends Iface> extends org.apache.thrift.ProcessFunction<I, addVrf_args> {
+ public addVrf() {
+ super("addVrf");
+ }
+
+ public addVrf_args getEmptyArgsInstance() {
+ return new addVrf_args();
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public addVrf_result getResult(I iface, addVrf_args args) throws org.apache.thrift.TException {
+ addVrf_result result = new addVrf_result();
+ result.success = iface.addVrf(args.rd, args.irts, args.erts);
+ result.setSuccessIsSet(true);
+ return result;
+ }
+ }
+
+ public static class delVrf<I extends Iface> extends org.apache.thrift.ProcessFunction<I, delVrf_args> {
+ public delVrf() {
+ super("delVrf");
+ }
+
+ public delVrf_args getEmptyArgsInstance() {
+ return new delVrf_args();
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public delVrf_result getResult(I iface, delVrf_args args) throws org.apache.thrift.TException {
+ delVrf_result result = new delVrf_result();
+ result.success = iface.delVrf(args.rd);
+ result.setSuccessIsSet(true);
+ return result;
+ }
+ }
+
+ public static class pushRoute<I extends Iface> extends org.apache.thrift.ProcessFunction<I, pushRoute_args> {
+ public pushRoute() {
+ super("pushRoute");
+ }
+
+ public pushRoute_args getEmptyArgsInstance() {
+ return new pushRoute_args();
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public pushRoute_result getResult(I iface, pushRoute_args args) throws org.apache.thrift.TException {
+ pushRoute_result result = new pushRoute_result();
+ result.success = iface.pushRoute(args.prefix, args.nexthop, args.rd, args.label);
+ result.setSuccessIsSet(true);
+ return result;
+ }
+ }
+
+ public static class withdrawRoute<I extends Iface> extends org.apache.thrift.ProcessFunction<I, withdrawRoute_args> {
+ public withdrawRoute() {
+ super("withdrawRoute");
+ }
+
+ public withdrawRoute_args getEmptyArgsInstance() {
+ return new withdrawRoute_args();
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public withdrawRoute_result getResult(I iface, withdrawRoute_args args) throws org.apache.thrift.TException {
+ withdrawRoute_result result = new withdrawRoute_result();
+ result.success = iface.withdrawRoute(args.prefix, args.rd);
+ result.setSuccessIsSet(true);
+ return result;
+ }
+ }
+
+ public static class setEbgpMultihop<I extends Iface> extends org.apache.thrift.ProcessFunction<I, setEbgpMultihop_args> {
+ public setEbgpMultihop() {
+ super("setEbgpMultihop");
+ }
+
+ public setEbgpMultihop_args getEmptyArgsInstance() {
+ return new setEbgpMultihop_args();
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public setEbgpMultihop_result getResult(I iface, setEbgpMultihop_args args) throws org.apache.thrift.TException {
+ setEbgpMultihop_result result = new setEbgpMultihop_result();
+ result.success = iface.setEbgpMultihop(args.peerIp, args.nHops);
+ result.setSuccessIsSet(true);
+ return result;
+ }
+ }
+
+ public static class unsetEbgpMultihop<I extends Iface> extends org.apache.thrift.ProcessFunction<I, unsetEbgpMultihop_args> {
+ public unsetEbgpMultihop() {
+ super("unsetEbgpMultihop");
+ }
+
+ public unsetEbgpMultihop_args getEmptyArgsInstance() {
+ return new unsetEbgpMultihop_args();
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public unsetEbgpMultihop_result getResult(I iface, unsetEbgpMultihop_args args) throws org.apache.thrift.TException {
+ unsetEbgpMultihop_result result = new unsetEbgpMultihop_result();
+ result.success = iface.unsetEbgpMultihop(args.peerIp);
+ result.setSuccessIsSet(true);
+ return result;
+ }
+ }
+
+ public static class setUpdateSource<I extends Iface> extends org.apache.thrift.ProcessFunction<I, setUpdateSource_args> {
+ public setUpdateSource() {
+ super("setUpdateSource");
+ }
+
+ public setUpdateSource_args getEmptyArgsInstance() {
+ return new setUpdateSource_args();
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public setUpdateSource_result getResult(I iface, setUpdateSource_args args) throws org.apache.thrift.TException {
+ setUpdateSource_result result = new setUpdateSource_result();
+ result.success = iface.setUpdateSource(args.peerIp, args.srcIp);
+ result.setSuccessIsSet(true);
+ return result;
+ }
+ }
+
+ public static class unsetUpdateSource<I extends Iface> extends org.apache.thrift.ProcessFunction<I, unsetUpdateSource_args> {
+ public unsetUpdateSource() {
+ super("unsetUpdateSource");
+ }
+
+ public unsetUpdateSource_args getEmptyArgsInstance() {
+ return new unsetUpdateSource_args();
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public unsetUpdateSource_result getResult(I iface, unsetUpdateSource_args args) throws org.apache.thrift.TException {
+ unsetUpdateSource_result result = new unsetUpdateSource_result();
+ result.success = iface.unsetUpdateSource(args.peerIp);
+ result.setSuccessIsSet(true);
+ return result;
+ }
+ }
+
+ public static class enableAddressFamily<I extends Iface> extends org.apache.thrift.ProcessFunction<I, enableAddressFamily_args> {
+ public enableAddressFamily() {
+ super("enableAddressFamily");
+ }
+
+ public enableAddressFamily_args getEmptyArgsInstance() {
+ return new enableAddressFamily_args();
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public enableAddressFamily_result getResult(I iface, enableAddressFamily_args args) throws org.apache.thrift.TException {
+ enableAddressFamily_result result = new enableAddressFamily_result();
+ result.success = iface.enableAddressFamily(args.peerIp, args.afi, args.safi);
+ result.setSuccessIsSet(true);
+ return result;
+ }
+ }
+
+ public static class disableAddressFamily<I extends Iface> extends org.apache.thrift.ProcessFunction<I, disableAddressFamily_args> {
+ public disableAddressFamily() {
+ super("disableAddressFamily");
+ }
+
+ public disableAddressFamily_args getEmptyArgsInstance() {
+ return new disableAddressFamily_args();
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public disableAddressFamily_result getResult(I iface, disableAddressFamily_args args) throws org.apache.thrift.TException {
+ disableAddressFamily_result result = new disableAddressFamily_result();
+ result.success = iface.disableAddressFamily(args.peerIp, args.afi, args.safi);
+ result.setSuccessIsSet(true);
+ return result;
+ }
+ }
+
+ public static class setLogConfig<I extends Iface> extends org.apache.thrift.ProcessFunction<I, setLogConfig_args> {
+ public setLogConfig() {
+ super("setLogConfig");
+ }
+
+ public setLogConfig_args getEmptyArgsInstance() {
+ return new setLogConfig_args();
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public setLogConfig_result getResult(I iface, setLogConfig_args args) throws org.apache.thrift.TException {
+ setLogConfig_result result = new setLogConfig_result();
+ result.success = iface.setLogConfig(args.logFileName, args.logLevel);
+ result.setSuccessIsSet(true);
+ return result;
+ }
+ }
+
+ public static class enableGracefulRestart<I extends Iface> extends org.apache.thrift.ProcessFunction<I, enableGracefulRestart_args> {
+ public enableGracefulRestart() {
+ super("enableGracefulRestart");
+ }
+
+ public enableGracefulRestart_args getEmptyArgsInstance() {
+ return new enableGracefulRestart_args();
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public enableGracefulRestart_result getResult(I iface, enableGracefulRestart_args args) throws org.apache.thrift.TException {
+ enableGracefulRestart_result result = new enableGracefulRestart_result();
+ result.success = iface.enableGracefulRestart(args.stalepathTime);
+ result.setSuccessIsSet(true);
+ return result;
+ }
+ }
+
+ public static class disableGracefulRestart<I extends Iface> extends org.apache.thrift.ProcessFunction<I, disableGracefulRestart_args> {
+ public disableGracefulRestart() {
+ super("disableGracefulRestart");
+ }
+
+ public disableGracefulRestart_args getEmptyArgsInstance() {
+ return new disableGracefulRestart_args();
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public disableGracefulRestart_result getResult(I iface, disableGracefulRestart_args args) throws org.apache.thrift.TException {
+ disableGracefulRestart_result result = new disableGracefulRestart_result();
+ result.success = iface.disableGracefulRestart();
+ result.setSuccessIsSet(true);
+ return result;
+ }
+ }
+
+ public static class getRoutes<I extends Iface> extends org.apache.thrift.ProcessFunction<I, getRoutes_args> {
+ public getRoutes() {
+ super("getRoutes");
+ }
+
+ public getRoutes_args getEmptyArgsInstance() {
+ return new getRoutes_args();
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public getRoutes_result getResult(I iface, getRoutes_args args) throws org.apache.thrift.TException {
+ getRoutes_result result = new getRoutes_result();
+ result.success = iface.getRoutes(args.optype, args.winSize);
+ return result;
+ }
+ }
+
+ }
+
+ public static class AsyncProcessor<I extends AsyncIface> extends org.apache.thrift.TBaseAsyncProcessor<I> {
+ private static final Logger LOGGER = LoggerFactory.getLogger(AsyncProcessor.class.getName());
+ public AsyncProcessor(I iface) {
+ super(iface, getProcessMap(new HashMap<String, org.apache.thrift.AsyncProcessFunction<I, ? extends org.apache.thrift.TBase, ?>>()));
+ }
+
+ protected AsyncProcessor(I iface, Map<String, org.apache.thrift.AsyncProcessFunction<I, ? extends org.apache.thrift.TBase, ?>> processMap) {
+ super(iface, getProcessMap(processMap));
+ }
+
+ private static <I extends AsyncIface> Map<String, org.apache.thrift.AsyncProcessFunction<I, ? extends org.apache.thrift.TBase,?>> getProcessMap(Map<String, org.apache.thrift.AsyncProcessFunction<I, ? extends org.apache.thrift.TBase, ?>> processMap) {
+ processMap.put("startBgp", new startBgp());
+ processMap.put("stopBgp", new stopBgp());
+ processMap.put("createPeer", new createPeer());
+ processMap.put("deletePeer", new deletePeer());
+ processMap.put("addVrf", new addVrf());
+ processMap.put("delVrf", new delVrf());
+ processMap.put("pushRoute", new pushRoute());
+ processMap.put("withdrawRoute", new withdrawRoute());
+ processMap.put("setEbgpMultihop", new setEbgpMultihop());
+ processMap.put("unsetEbgpMultihop", new unsetEbgpMultihop());
+ processMap.put("setUpdateSource", new setUpdateSource());
+ processMap.put("unsetUpdateSource", new unsetUpdateSource());
+ processMap.put("enableAddressFamily", new enableAddressFamily());
+ processMap.put("disableAddressFamily", new disableAddressFamily());
+ processMap.put("setLogConfig", new setLogConfig());
+ processMap.put("enableGracefulRestart", new enableGracefulRestart());
+ processMap.put("disableGracefulRestart", new disableGracefulRestart());
+ processMap.put("getRoutes", new getRoutes());
+ return processMap;
+ }
+
+ public static class startBgp<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, startBgp_args, Integer> {
+ public startBgp() {
+ super("startBgp");
+ }
+
+ public startBgp_args getEmptyArgsInstance() {
+ return new startBgp_args();
+ }
+
+ public AsyncMethodCallback<Integer> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Integer>() {
+ public void onComplete(Integer o) {
+ startBgp_result result = new startBgp_result();
+ result.success = o;
+ result.setSuccessIsSet(true);
+ try {
+ fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
+ return;
+ } catch (Exception e) {
+ LOGGER.error("Exception writing to internal frame buffer", e);
+ }
+ fb.close();
+ }
+ public void onError(Exception e) {
+ byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
+ org.apache.thrift.TBase msg;
+ startBgp_result result = new startBgp_result();
+ {
+ msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
+ msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
+ }
+ try {
+ fcall.sendResponse(fb,msg,msgType,seqid);
+ return;
+ } catch (Exception ex) {
+ LOGGER.error("Exception writing to internal frame buffer", ex);
+ }
+ fb.close();
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public void start(I iface, startBgp_args args, org.apache.thrift.async.AsyncMethodCallback<Integer> resultHandler) throws TException {
+ iface.startBgp(args.asNumber, args.routerId, args.port, args.holdTime, args.keepAliveTime, args.stalepathTime, args.announceFbit,resultHandler);
+ }
+ }
+
+ public static class stopBgp<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, stopBgp_args, Integer> {
+ public stopBgp() {
+ super("stopBgp");
+ }
+
+ public stopBgp_args getEmptyArgsInstance() {
+ return new stopBgp_args();
+ }
+
+ public AsyncMethodCallback<Integer> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Integer>() {
+ public void onComplete(Integer o) {
+ stopBgp_result result = new stopBgp_result();
+ result.success = o;
+ result.setSuccessIsSet(true);
+ try {
+ fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
+ return;
+ } catch (Exception e) {
+ LOGGER.error("Exception writing to internal frame buffer", e);
+ }
+ fb.close();
+ }
+ public void onError(Exception e) {
+ byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
+ org.apache.thrift.TBase msg;
+ stopBgp_result result = new stopBgp_result();
+ {
+ msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
+ msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
+ }
+ try {
+ fcall.sendResponse(fb,msg,msgType,seqid);
+ return;
+ } catch (Exception ex) {
+ LOGGER.error("Exception writing to internal frame buffer", ex);
+ }
+ fb.close();
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public void start(I iface, stopBgp_args args, org.apache.thrift.async.AsyncMethodCallback<Integer> resultHandler) throws TException {
+ iface.stopBgp(args.asNumber,resultHandler);
+ }
+ }
+
+ public static class createPeer<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, createPeer_args, Integer> {
+ public createPeer() {
+ super("createPeer");
+ }
+
+ public createPeer_args getEmptyArgsInstance() {
+ return new createPeer_args();
+ }
+
+ public AsyncMethodCallback<Integer> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Integer>() {
+ public void onComplete(Integer o) {
+ createPeer_result result = new createPeer_result();
+ result.success = o;
+ result.setSuccessIsSet(true);
+ try {
+ fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
+ return;
+ } catch (Exception e) {
+ LOGGER.error("Exception writing to internal frame buffer", e);
+ }
+ fb.close();
+ }
+ public void onError(Exception e) {
+ byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
+ org.apache.thrift.TBase msg;
+ createPeer_result result = new createPeer_result();
+ {
+ msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
+ msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
+ }
+ try {
+ fcall.sendResponse(fb,msg,msgType,seqid);
+ return;
+ } catch (Exception ex) {
+ LOGGER.error("Exception writing to internal frame buffer", ex);
+ }
+ fb.close();
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public void start(I iface, createPeer_args args, org.apache.thrift.async.AsyncMethodCallback<Integer> resultHandler) throws TException {
+ iface.createPeer(args.ipAddress, args.asNumber,resultHandler);
+ }
+ }
+
+ public static class deletePeer<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, deletePeer_args, Integer> {
+ public deletePeer() {
+ super("deletePeer");
+ }
+
+ public deletePeer_args getEmptyArgsInstance() {
+ return new deletePeer_args();
+ }
+
+ public AsyncMethodCallback<Integer> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Integer>() {
+ public void onComplete(Integer o) {
+ deletePeer_result result = new deletePeer_result();
+ result.success = o;
+ result.setSuccessIsSet(true);
+ try {
+ fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
+ return;
+ } catch (Exception e) {
+ LOGGER.error("Exception writing to internal frame buffer", e);
+ }
+ fb.close();
+ }
+ public void onError(Exception e) {
+ byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
+ org.apache.thrift.TBase msg;
+ deletePeer_result result = new deletePeer_result();
+ {
+ msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
+ msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
+ }
+ try {
+ fcall.sendResponse(fb,msg,msgType,seqid);
+ return;
+ } catch (Exception ex) {
+ LOGGER.error("Exception writing to internal frame buffer", ex);
+ }
+ fb.close();
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public void start(I iface, deletePeer_args args, org.apache.thrift.async.AsyncMethodCallback<Integer> resultHandler) throws TException {
+ iface.deletePeer(args.ipAddress,resultHandler);
+ }
+ }
+
+ public static class addVrf<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, addVrf_args, Integer> {
+ public addVrf() {
+ super("addVrf");
+ }
+
+ public addVrf_args getEmptyArgsInstance() {
+ return new addVrf_args();
+ }
+
+ public AsyncMethodCallback<Integer> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Integer>() {
+ public void onComplete(Integer o) {
+ addVrf_result result = new addVrf_result();
+ result.success = o;
+ result.setSuccessIsSet(true);
+ try {
+ fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
+ return;
+ } catch (Exception e) {
+ LOGGER.error("Exception writing to internal frame buffer", e);
+ }
+ fb.close();
+ }
+ public void onError(Exception e) {
+ byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
+ org.apache.thrift.TBase msg;
+ addVrf_result result = new addVrf_result();
+ {
+ msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
+ msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
+ }
+ try {
+ fcall.sendResponse(fb,msg,msgType,seqid);
+ return;
+ } catch (Exception ex) {
+ LOGGER.error("Exception writing to internal frame buffer", ex);
+ }
+ fb.close();
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public void start(I iface, addVrf_args args, org.apache.thrift.async.AsyncMethodCallback<Integer> resultHandler) throws TException {
+ iface.addVrf(args.rd, args.irts, args.erts,resultHandler);
+ }
+ }
+
+ public static class delVrf<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, delVrf_args, Integer> {
+ public delVrf() {
+ super("delVrf");
+ }
+
+ public delVrf_args getEmptyArgsInstance() {
+ return new delVrf_args();
+ }
+
+ public AsyncMethodCallback<Integer> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Integer>() {
+ public void onComplete(Integer o) {
+ delVrf_result result = new delVrf_result();
+ result.success = o;
+ result.setSuccessIsSet(true);
+ try {
+ fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
+ return;
+ } catch (Exception e) {
+ LOGGER.error("Exception writing to internal frame buffer", e);
+ }
+ fb.close();
+ }
+ public void onError(Exception e) {
+ byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
+ org.apache.thrift.TBase msg;
+ delVrf_result result = new delVrf_result();
+ {
+ msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
+ msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
+ }
+ try {
+ fcall.sendResponse(fb,msg,msgType,seqid);
+ return;
+ } catch (Exception ex) {
+ LOGGER.error("Exception writing to internal frame buffer", ex);
+ }
+ fb.close();
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public void start(I iface, delVrf_args args, org.apache.thrift.async.AsyncMethodCallback<Integer> resultHandler) throws TException {
+ iface.delVrf(args.rd,resultHandler);
+ }
+ }
+
+ public static class pushRoute<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, pushRoute_args, Integer> {
+ public pushRoute() {
+ super("pushRoute");
+ }
+
+ public pushRoute_args getEmptyArgsInstance() {
+ return new pushRoute_args();
+ }
+
+ public AsyncMethodCallback<Integer> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Integer>() {
+ public void onComplete(Integer o) {
+ pushRoute_result result = new pushRoute_result();
+ result.success = o;
+ result.setSuccessIsSet(true);
+ try {
+ fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
+ return;
+ } catch (Exception e) {
+ LOGGER.error("Exception writing to internal frame buffer", e);
+ }
+ fb.close();
+ }
+ public void onError(Exception e) {
+ byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
+ org.apache.thrift.TBase msg;
+ pushRoute_result result = new pushRoute_result();
+ {
+ msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
+ msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
+ }
+ try {
+ fcall.sendResponse(fb,msg,msgType,seqid);
+ return;
+ } catch (Exception ex) {
+ LOGGER.error("Exception writing to internal frame buffer", ex);
+ }
+ fb.close();
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public void start(I iface, pushRoute_args args, org.apache.thrift.async.AsyncMethodCallback<Integer> resultHandler) throws TException {
+ iface.pushRoute(args.prefix, args.nexthop, args.rd, args.label,resultHandler);
+ }
+ }
+
+ public static class withdrawRoute<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, withdrawRoute_args, Integer> {
+ public withdrawRoute() {
+ super("withdrawRoute");
+ }
+
+ public withdrawRoute_args getEmptyArgsInstance() {
+ return new withdrawRoute_args();
+ }
+
+ public AsyncMethodCallback<Integer> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Integer>() {
+ public void onComplete(Integer o) {
+ withdrawRoute_result result = new withdrawRoute_result();
+ result.success = o;
+ result.setSuccessIsSet(true);
+ try {
+ fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
+ return;
+ } catch (Exception e) {
+ LOGGER.error("Exception writing to internal frame buffer", e);
+ }
+ fb.close();
+ }
+ public void onError(Exception e) {
+ byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
+ org.apache.thrift.TBase msg;
+ withdrawRoute_result result = new withdrawRoute_result();
+ {
+ msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
+ msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
+ }
+ try {
+ fcall.sendResponse(fb,msg,msgType,seqid);
+ return;
+ } catch (Exception ex) {
+ LOGGER.error("Exception writing to internal frame buffer", ex);
+ }
+ fb.close();
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public void start(I iface, withdrawRoute_args args, org.apache.thrift.async.AsyncMethodCallback<Integer> resultHandler) throws TException {
+ iface.withdrawRoute(args.prefix, args.rd,resultHandler);
+ }
+ }
+
+ public static class setEbgpMultihop<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, setEbgpMultihop_args, Integer> {
+ public setEbgpMultihop() {
+ super("setEbgpMultihop");
+ }
+
+ public setEbgpMultihop_args getEmptyArgsInstance() {
+ return new setEbgpMultihop_args();
+ }
+
+ public AsyncMethodCallback<Integer> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Integer>() {
+ public void onComplete(Integer o) {
+ setEbgpMultihop_result result = new setEbgpMultihop_result();
+ result.success = o;
+ result.setSuccessIsSet(true);
+ try {
+ fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
+ return;
+ } catch (Exception e) {
+ LOGGER.error("Exception writing to internal frame buffer", e);
+ }
+ fb.close();
+ }
+ public void onError(Exception e) {
+ byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
+ org.apache.thrift.TBase msg;
+ setEbgpMultihop_result result = new setEbgpMultihop_result();
+ {
+ msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
+ msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
+ }
+ try {
+ fcall.sendResponse(fb,msg,msgType,seqid);
+ return;
+ } catch (Exception ex) {
+ LOGGER.error("Exception writing to internal frame buffer", ex);
+ }
+ fb.close();
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public void start(I iface, setEbgpMultihop_args args, org.apache.thrift.async.AsyncMethodCallback<Integer> resultHandler) throws TException {
+ iface.setEbgpMultihop(args.peerIp, args.nHops,resultHandler);
+ }
+ }
+
+ public static class unsetEbgpMultihop<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, unsetEbgpMultihop_args, Integer> {
+ public unsetEbgpMultihop() {
+ super("unsetEbgpMultihop");
+ }
+
+ public unsetEbgpMultihop_args getEmptyArgsInstance() {
+ return new unsetEbgpMultihop_args();
+ }
+
+ public AsyncMethodCallback<Integer> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Integer>() {
+ public void onComplete(Integer o) {
+ unsetEbgpMultihop_result result = new unsetEbgpMultihop_result();
+ result.success = o;
+ result.setSuccessIsSet(true);
+ try {
+ fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
+ return;
+ } catch (Exception e) {
+ LOGGER.error("Exception writing to internal frame buffer", e);
+ }
+ fb.close();
+ }
+ public void onError(Exception e) {
+ byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
+ org.apache.thrift.TBase msg;
+ unsetEbgpMultihop_result result = new unsetEbgpMultihop_result();
+ {
+ msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
+ msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
+ }
+ try {
+ fcall.sendResponse(fb,msg,msgType,seqid);
+ return;
+ } catch (Exception ex) {
+ LOGGER.error("Exception writing to internal frame buffer", ex);
+ }
+ fb.close();
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public void start(I iface, unsetEbgpMultihop_args args, org.apache.thrift.async.AsyncMethodCallback<Integer> resultHandler) throws TException {
+ iface.unsetEbgpMultihop(args.peerIp,resultHandler);
+ }
+ }
+
+ public static class setUpdateSource<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, setUpdateSource_args, Integer> {
+ public setUpdateSource() {
+ super("setUpdateSource");
+ }
+
+ public setUpdateSource_args getEmptyArgsInstance() {
+ return new setUpdateSource_args();
+ }
+
+ public AsyncMethodCallback<Integer> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Integer>() {
+ public void onComplete(Integer o) {
+ setUpdateSource_result result = new setUpdateSource_result();
+ result.success = o;
+ result.setSuccessIsSet(true);
+ try {
+ fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
+ return;
+ } catch (Exception e) {
+ LOGGER.error("Exception writing to internal frame buffer", e);
+ }
+ fb.close();
+ }
+ public void onError(Exception e) {
+ byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
+ org.apache.thrift.TBase msg;
+ setUpdateSource_result result = new setUpdateSource_result();
+ {
+ msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
+ msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
+ }
+ try {
+ fcall.sendResponse(fb,msg,msgType,seqid);
+ return;
+ } catch (Exception ex) {
+ LOGGER.error("Exception writing to internal frame buffer", ex);
+ }
+ fb.close();
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public void start(I iface, setUpdateSource_args args, org.apache.thrift.async.AsyncMethodCallback<Integer> resultHandler) throws TException {
+ iface.setUpdateSource(args.peerIp, args.srcIp,resultHandler);
+ }
+ }
+
+ public static class unsetUpdateSource<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, unsetUpdateSource_args, Integer> {
+ public unsetUpdateSource() {
+ super("unsetUpdateSource");
+ }
+
+ public unsetUpdateSource_args getEmptyArgsInstance() {
+ return new unsetUpdateSource_args();
+ }
+
+ public AsyncMethodCallback<Integer> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Integer>() {
+ public void onComplete(Integer o) {
+ unsetUpdateSource_result result = new unsetUpdateSource_result();
+ result.success = o;
+ result.setSuccessIsSet(true);
+ try {
+ fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
+ return;
+ } catch (Exception e) {
+ LOGGER.error("Exception writing to internal frame buffer", e);
+ }
+ fb.close();
+ }
+ public void onError(Exception e) {
+ byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
+ org.apache.thrift.TBase msg;
+ unsetUpdateSource_result result = new unsetUpdateSource_result();
+ {
+ msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
+ msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
+ }
+ try {
+ fcall.sendResponse(fb,msg,msgType,seqid);
+ return;
+ } catch (Exception ex) {
+ LOGGER.error("Exception writing to internal frame buffer", ex);
+ }
+ fb.close();
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public void start(I iface, unsetUpdateSource_args args, org.apache.thrift.async.AsyncMethodCallback<Integer> resultHandler) throws TException {
+ iface.unsetUpdateSource(args.peerIp,resultHandler);
+ }
+ }
+
+ public static class enableAddressFamily<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, enableAddressFamily_args, Integer> {
+ public enableAddressFamily() {
+ super("enableAddressFamily");
+ }
+
+ public enableAddressFamily_args getEmptyArgsInstance() {
+ return new enableAddressFamily_args();
+ }
+
+ public AsyncMethodCallback<Integer> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Integer>() {
+ public void onComplete(Integer o) {
+ enableAddressFamily_result result = new enableAddressFamily_result();
+ result.success = o;
+ result.setSuccessIsSet(true);
+ try {
+ fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
+ return;
+ } catch (Exception e) {
+ LOGGER.error("Exception writing to internal frame buffer", e);
+ }
+ fb.close();
+ }
+ public void onError(Exception e) {
+ byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
+ org.apache.thrift.TBase msg;
+ enableAddressFamily_result result = new enableAddressFamily_result();
+ {
+ msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
+ msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
+ }
+ try {
+ fcall.sendResponse(fb,msg,msgType,seqid);
+ return;
+ } catch (Exception ex) {
+ LOGGER.error("Exception writing to internal frame buffer", ex);
+ }
+ fb.close();
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public void start(I iface, enableAddressFamily_args args, org.apache.thrift.async.AsyncMethodCallback<Integer> resultHandler) throws TException {
+ iface.enableAddressFamily(args.peerIp, args.afi, args.safi,resultHandler);
+ }
+ }
+
+ public static class disableAddressFamily<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, disableAddressFamily_args, Integer> {
+ public disableAddressFamily() {
+ super("disableAddressFamily");
+ }
+
+ public disableAddressFamily_args getEmptyArgsInstance() {
+ return new disableAddressFamily_args();
+ }
+
+ public AsyncMethodCallback<Integer> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Integer>() {
+ public void onComplete(Integer o) {
+ disableAddressFamily_result result = new disableAddressFamily_result();
+ result.success = o;
+ result.setSuccessIsSet(true);
+ try {
+ fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
+ return;
+ } catch (Exception e) {
+ LOGGER.error("Exception writing to internal frame buffer", e);
+ }
+ fb.close();
+ }
+ public void onError(Exception e) {
+ byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
+ org.apache.thrift.TBase msg;
+ disableAddressFamily_result result = new disableAddressFamily_result();
+ {
+ msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
+ msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
+ }
+ try {
+ fcall.sendResponse(fb,msg,msgType,seqid);
+ return;
+ } catch (Exception ex) {
+ LOGGER.error("Exception writing to internal frame buffer", ex);
+ }
+ fb.close();
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public void start(I iface, disableAddressFamily_args args, org.apache.thrift.async.AsyncMethodCallback<Integer> resultHandler) throws TException {
+ iface.disableAddressFamily(args.peerIp, args.afi, args.safi,resultHandler);
+ }
+ }
+
+ public static class setLogConfig<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, setLogConfig_args, Integer> {
+ public setLogConfig() {
+ super("setLogConfig");
+ }
+
+ public setLogConfig_args getEmptyArgsInstance() {
+ return new setLogConfig_args();
+ }
+
+ public AsyncMethodCallback<Integer> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Integer>() {
+ public void onComplete(Integer o) {
+ setLogConfig_result result = new setLogConfig_result();
+ result.success = o;
+ result.setSuccessIsSet(true);
+ try {
+ fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
+ return;
+ } catch (Exception e) {
+ LOGGER.error("Exception writing to internal frame buffer", e);
+ }
+ fb.close();
+ }
+ public void onError(Exception e) {
+ byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
+ org.apache.thrift.TBase msg;
+ setLogConfig_result result = new setLogConfig_result();
+ {
+ msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
+ msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
+ }
+ try {
+ fcall.sendResponse(fb,msg,msgType,seqid);
+ return;
+ } catch (Exception ex) {
+ LOGGER.error("Exception writing to internal frame buffer", ex);
+ }
+ fb.close();
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public void start(I iface, setLogConfig_args args, org.apache.thrift.async.AsyncMethodCallback<Integer> resultHandler) throws TException {
+ iface.setLogConfig(args.logFileName, args.logLevel,resultHandler);
+ }
+ }
+
+ public static class enableGracefulRestart<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, enableGracefulRestart_args, Integer> {
+ public enableGracefulRestart() {
+ super("enableGracefulRestart");
+ }
+
+ public enableGracefulRestart_args getEmptyArgsInstance() {
+ return new enableGracefulRestart_args();
+ }
+
+ public AsyncMethodCallback<Integer> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Integer>() {
+ public void onComplete(Integer o) {
+ enableGracefulRestart_result result = new enableGracefulRestart_result();
+ result.success = o;
+ result.setSuccessIsSet(true);
+ try {
+ fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
+ return;
+ } catch (Exception e) {
+ LOGGER.error("Exception writing to internal frame buffer", e);
+ }
+ fb.close();
+ }
+ public void onError(Exception e) {
+ byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
+ org.apache.thrift.TBase msg;
+ enableGracefulRestart_result result = new enableGracefulRestart_result();
+ {
+ msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
+ msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
+ }
+ try {
+ fcall.sendResponse(fb,msg,msgType,seqid);
+ return;
+ } catch (Exception ex) {
+ LOGGER.error("Exception writing to internal frame buffer", ex);
+ }
+ fb.close();
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public void start(I iface, enableGracefulRestart_args args, org.apache.thrift.async.AsyncMethodCallback<Integer> resultHandler) throws TException {
+ iface.enableGracefulRestart(args.stalepathTime,resultHandler);
+ }
+ }
+
+ public static class disableGracefulRestart<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, disableGracefulRestart_args, Integer> {
+ public disableGracefulRestart() {
+ super("disableGracefulRestart");
+ }
+
+ public disableGracefulRestart_args getEmptyArgsInstance() {
+ return new disableGracefulRestart_args();
+ }
+
+ public AsyncMethodCallback<Integer> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Integer>() {
+ public void onComplete(Integer o) {
+ disableGracefulRestart_result result = new disableGracefulRestart_result();
+ result.success = o;
+ result.setSuccessIsSet(true);
+ try {
+ fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
+ return;
+ } catch (Exception e) {
+ LOGGER.error("Exception writing to internal frame buffer", e);
+ }
+ fb.close();
+ }
+ public void onError(Exception e) {
+ byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
+ org.apache.thrift.TBase msg;
+ disableGracefulRestart_result result = new disableGracefulRestart_result();
+ {
+ msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
+ msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
+ }
+ try {
+ fcall.sendResponse(fb,msg,msgType,seqid);
+ return;
+ } catch (Exception ex) {
+ LOGGER.error("Exception writing to internal frame buffer", ex);
+ }
+ fb.close();
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public void start(I iface, disableGracefulRestart_args args, org.apache.thrift.async.AsyncMethodCallback<Integer> resultHandler) throws TException {
+ iface.disableGracefulRestart(resultHandler);
+ }
+ }
+
+ public static class getRoutes<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, getRoutes_args, Routes> {
+ public getRoutes() {
+ super("getRoutes");
+ }
+
+ public getRoutes_args getEmptyArgsInstance() {
+ return new getRoutes_args();
+ }
+
+ public AsyncMethodCallback<Routes> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Routes>() {
+ public void onComplete(Routes o) {
+ getRoutes_result result = new getRoutes_result();
+ result.success = o;
+ try {
+ fcall.sendResponse(fb,result, org.apache.thrift.protocol.TMessageType.REPLY,seqid);
+ return;
+ } catch (Exception e) {
+ LOGGER.error("Exception writing to internal frame buffer", e);
+ }
+ fb.close();
+ }
+ public void onError(Exception e) {
+ byte msgType = org.apache.thrift.protocol.TMessageType.REPLY;
+ org.apache.thrift.TBase msg;
+ getRoutes_result result = new getRoutes_result();
+ {
+ msgType = org.apache.thrift.protocol.TMessageType.EXCEPTION;
+ msg = (org.apache.thrift.TBase)new org.apache.thrift.TApplicationException(org.apache.thrift.TApplicationException.INTERNAL_ERROR, e.getMessage());
+ }
+ try {
+ fcall.sendResponse(fb,msg,msgType,seqid);
+ return;
+ } catch (Exception ex) {
+ LOGGER.error("Exception writing to internal frame buffer", ex);
+ }
+ fb.close();
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return false;
+ }
+
+ public void start(I iface, getRoutes_args args, org.apache.thrift.async.AsyncMethodCallback<Routes> resultHandler) throws TException {
+ iface.getRoutes(args.optype, args.winSize,resultHandler);
+ }
+ }
+
+ }
+
+ public static class startBgp_args implements org.apache.thrift.TBase<startBgp_args, startBgp_args._Fields>, java.io.Serializable, Cloneable, Comparable<startBgp_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("startBgp_args");
+
+ private static final org.apache.thrift.protocol.TField AS_NUMBER_FIELD_DESC = new org.apache.thrift.protocol.TField("asNumber", org.apache.thrift.protocol.TType.I32, (short)1);
+ private static final org.apache.thrift.protocol.TField ROUTER_ID_FIELD_DESC = new org.apache.thrift.protocol.TField("routerId", org.apache.thrift.protocol.TType.STRING, (short)2);
+ private static final org.apache.thrift.protocol.TField PORT_FIELD_DESC = new org.apache.thrift.protocol.TField("port", org.apache.thrift.protocol.TType.I32, (short)3);
+ private static final org.apache.thrift.protocol.TField HOLD_TIME_FIELD_DESC = new org.apache.thrift.protocol.TField("holdTime", org.apache.thrift.protocol.TType.I32, (short)4);
+ private static final org.apache.thrift.protocol.TField KEEP_ALIVE_TIME_FIELD_DESC = new org.apache.thrift.protocol.TField("keepAliveTime", org.apache.thrift.protocol.TType.I32, (short)5);
+ private static final org.apache.thrift.protocol.TField STALEPATH_TIME_FIELD_DESC = new org.apache.thrift.protocol.TField("stalepathTime", org.apache.thrift.protocol.TType.I32, (short)6);
+ private static final org.apache.thrift.protocol.TField ANNOUNCE_FBIT_FIELD_DESC = new org.apache.thrift.protocol.TField("announceFbit", org.apache.thrift.protocol.TType.BOOL, (short)7);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new startBgp_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new startBgp_argsTupleSchemeFactory());
+ }
+
+ public int asNumber; // required
+ public String routerId; // required
+ public int port; // required
+ public int holdTime; // required
+ public int keepAliveTime; // required
+ public int stalepathTime; // required
+ public boolean announceFbit; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ AS_NUMBER((short)1, "asNumber"),
+ ROUTER_ID((short)2, "routerId"),
+ PORT((short)3, "port"),
+ HOLD_TIME((short)4, "holdTime"),
+ KEEP_ALIVE_TIME((short)5, "keepAliveTime"),
+ STALEPATH_TIME((short)6, "stalepathTime"),
+ ANNOUNCE_FBIT((short)7, "announceFbit");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // AS_NUMBER
+ return AS_NUMBER;
+ case 2: // ROUTER_ID
+ return ROUTER_ID;
+ case 3: // PORT
+ return PORT;
+ case 4: // HOLD_TIME
+ return HOLD_TIME;
+ case 5: // KEEP_ALIVE_TIME
+ return KEEP_ALIVE_TIME;
+ case 6: // STALEPATH_TIME
+ return STALEPATH_TIME;
+ case 7: // ANNOUNCE_FBIT
+ return ANNOUNCE_FBIT;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __ASNUMBER_ISSET_ID = 0;
+ private static final int __PORT_ISSET_ID = 1;
+ private static final int __HOLDTIME_ISSET_ID = 2;
+ private static final int __KEEPALIVETIME_ISSET_ID = 3;
+ private static final int __STALEPATHTIME_ISSET_ID = 4;
+ private static final int __ANNOUNCEFBIT_ISSET_ID = 5;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.AS_NUMBER, new org.apache.thrift.meta_data.FieldMetaData("asNumber", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ tmpMap.put(_Fields.ROUTER_ID, new org.apache.thrift.meta_data.FieldMetaData("routerId", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ tmpMap.put(_Fields.PORT, new org.apache.thrift.meta_data.FieldMetaData("port", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ tmpMap.put(_Fields.HOLD_TIME, new org.apache.thrift.meta_data.FieldMetaData("holdTime", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ tmpMap.put(_Fields.KEEP_ALIVE_TIME, new org.apache.thrift.meta_data.FieldMetaData("keepAliveTime", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ tmpMap.put(_Fields.STALEPATH_TIME, new org.apache.thrift.meta_data.FieldMetaData("stalepathTime", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ tmpMap.put(_Fields.ANNOUNCE_FBIT, new org.apache.thrift.meta_data.FieldMetaData("announceFbit", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BOOL)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(startBgp_args.class, metaDataMap);
+ }
+
+ public startBgp_args() {
+ }
+
+ public startBgp_args(
+ int asNumber,
+ String routerId,
+ int port,
+ int holdTime,
+ int keepAliveTime,
+ int stalepathTime,
+ boolean announceFbit)
+ {
+ this();
+ this.asNumber = asNumber;
+ setAsNumberIsSet(true);
+ this.routerId = routerId;
+ this.port = port;
+ setPortIsSet(true);
+ this.holdTime = holdTime;
+ setHoldTimeIsSet(true);
+ this.keepAliveTime = keepAliveTime;
+ setKeepAliveTimeIsSet(true);
+ this.stalepathTime = stalepathTime;
+ setStalepathTimeIsSet(true);
+ this.announceFbit = announceFbit;
+ setAnnounceFbitIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public startBgp_args(startBgp_args other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.asNumber = other.asNumber;
+ if (other.isSetRouterId()) {
+ this.routerId = other.routerId;
+ }
+ this.port = other.port;
+ this.holdTime = other.holdTime;
+ this.keepAliveTime = other.keepAliveTime;
+ this.stalepathTime = other.stalepathTime;
+ this.announceFbit = other.announceFbit;
+ }
+
+ public startBgp_args deepCopy() {
+ return new startBgp_args(this);
+ }
+
+ @Override
+ public void clear() {
+ setAsNumberIsSet(false);
+ this.asNumber = 0;
+ this.routerId = null;
+ setPortIsSet(false);
+ this.port = 0;
+ setHoldTimeIsSet(false);
+ this.holdTime = 0;
+ setKeepAliveTimeIsSet(false);
+ this.keepAliveTime = 0;
+ setStalepathTimeIsSet(false);
+ this.stalepathTime = 0;
+ setAnnounceFbitIsSet(false);
+ this.announceFbit = false;
+ }
+
+ public int getAsNumber() {
+ return this.asNumber;
+ }
+
+ public startBgp_args setAsNumber(int asNumber) {
+ this.asNumber = asNumber;
+ setAsNumberIsSet(true);
+ return this;
+ }
+
+ public void unsetAsNumber() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __ASNUMBER_ISSET_ID);
+ }
+
+ /** Returns true if field asNumber is set (has been assigned a value) and false otherwise */
+ public boolean isSetAsNumber() {
+ return EncodingUtils.testBit(__isset_bitfield, __ASNUMBER_ISSET_ID);
+ }
+
+ public void setAsNumberIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __ASNUMBER_ISSET_ID, value);
+ }
+
+ public String getRouterId() {
+ return this.routerId;
+ }
+
+ public startBgp_args setRouterId(String routerId) {
+ this.routerId = routerId;
+ return this;
+ }
+
+ public void unsetRouterId() {
+ this.routerId = null;
+ }
+
+ /** Returns true if field routerId is set (has been assigned a value) and false otherwise */
+ public boolean isSetRouterId() {
+ return this.routerId != null;
+ }
+
+ public void setRouterIdIsSet(boolean value) {
+ if (!value) {
+ this.routerId = null;
+ }
+ }
+
+ public int getPort() {
+ return this.port;
+ }
+
+ public startBgp_args setPort(int port) {
+ this.port = port;
+ setPortIsSet(true);
+ return this;
+ }
+
+ public void unsetPort() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __PORT_ISSET_ID);
+ }
+
+ /** Returns true if field port is set (has been assigned a value) and false otherwise */
+ public boolean isSetPort() {
+ return EncodingUtils.testBit(__isset_bitfield, __PORT_ISSET_ID);
+ }
+
+ public void setPortIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __PORT_ISSET_ID, value);
+ }
+
+ public int getHoldTime() {
+ return this.holdTime;
+ }
+
+ public startBgp_args setHoldTime(int holdTime) {
+ this.holdTime = holdTime;
+ setHoldTimeIsSet(true);
+ return this;
+ }
+
+ public void unsetHoldTime() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __HOLDTIME_ISSET_ID);
+ }
+
+ /** Returns true if field holdTime is set (has been assigned a value) and false otherwise */
+ public boolean isSetHoldTime() {
+ return EncodingUtils.testBit(__isset_bitfield, __HOLDTIME_ISSET_ID);
+ }
+
+ public void setHoldTimeIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __HOLDTIME_ISSET_ID, value);
+ }
+
+ public int getKeepAliveTime() {
+ return this.keepAliveTime;
+ }
+
+ public startBgp_args setKeepAliveTime(int keepAliveTime) {
+ this.keepAliveTime = keepAliveTime;
+ setKeepAliveTimeIsSet(true);
+ return this;
+ }
+
+ public void unsetKeepAliveTime() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __KEEPALIVETIME_ISSET_ID);
+ }
+
+ /** Returns true if field keepAliveTime is set (has been assigned a value) and false otherwise */
+ public boolean isSetKeepAliveTime() {
+ return EncodingUtils.testBit(__isset_bitfield, __KEEPALIVETIME_ISSET_ID);
+ }
+
+ public void setKeepAliveTimeIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __KEEPALIVETIME_ISSET_ID, value);
+ }
+
+ public int getStalepathTime() {
+ return this.stalepathTime;
+ }
+
+ public startBgp_args setStalepathTime(int stalepathTime) {
+ this.stalepathTime = stalepathTime;
+ setStalepathTimeIsSet(true);
+ return this;
+ }
+
+ public void unsetStalepathTime() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __STALEPATHTIME_ISSET_ID);
+ }
+
+ /** Returns true if field stalepathTime is set (has been assigned a value) and false otherwise */
+ public boolean isSetStalepathTime() {
+ return EncodingUtils.testBit(__isset_bitfield, __STALEPATHTIME_ISSET_ID);
+ }
+
+ public void setStalepathTimeIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __STALEPATHTIME_ISSET_ID, value);
+ }
+
+ public boolean isAnnounceFbit() {
+ return this.announceFbit;
+ }
+
+ public startBgp_args setAnnounceFbit(boolean announceFbit) {
+ this.announceFbit = announceFbit;
+ setAnnounceFbitIsSet(true);
+ return this;
+ }
+
+ public void unsetAnnounceFbit() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __ANNOUNCEFBIT_ISSET_ID);
+ }
+
+ /** Returns true if field announceFbit is set (has been assigned a value) and false otherwise */
+ public boolean isSetAnnounceFbit() {
+ return EncodingUtils.testBit(__isset_bitfield, __ANNOUNCEFBIT_ISSET_ID);
+ }
+
+ public void setAnnounceFbitIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __ANNOUNCEFBIT_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case AS_NUMBER:
+ if (value == null) {
+ unsetAsNumber();
+ } else {
+ setAsNumber((Integer)value);
+ }
+ break;
+
+ case ROUTER_ID:
+ if (value == null) {
+ unsetRouterId();
+ } else {
+ setRouterId((String)value);
+ }
+ break;
+
+ case PORT:
+ if (value == null) {
+ unsetPort();
+ } else {
+ setPort((Integer)value);
+ }
+ break;
+
+ case HOLD_TIME:
+ if (value == null) {
+ unsetHoldTime();
+ } else {
+ setHoldTime((Integer)value);
+ }
+ break;
+
+ case KEEP_ALIVE_TIME:
+ if (value == null) {
+ unsetKeepAliveTime();
+ } else {
+ setKeepAliveTime((Integer)value);
+ }
+ break;
+
+ case STALEPATH_TIME:
+ if (value == null) {
+ unsetStalepathTime();
+ } else {
+ setStalepathTime((Integer)value);
+ }
+ break;
+
+ case ANNOUNCE_FBIT:
+ if (value == null) {
+ unsetAnnounceFbit();
+ } else {
+ setAnnounceFbit((Boolean)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case AS_NUMBER:
+ return Integer.valueOf(getAsNumber());
+
+ case ROUTER_ID:
+ return getRouterId();
+
+ case PORT:
+ return Integer.valueOf(getPort());
+
+ case HOLD_TIME:
+ return Integer.valueOf(getHoldTime());
+
+ case KEEP_ALIVE_TIME:
+ return Integer.valueOf(getKeepAliveTime());
+
+ case STALEPATH_TIME:
+ return Integer.valueOf(getStalepathTime());
+
+ case ANNOUNCE_FBIT:
+ return Boolean.valueOf(isAnnounceFbit());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case AS_NUMBER:
+ return isSetAsNumber();
+ case ROUTER_ID:
+ return isSetRouterId();
+ case PORT:
+ return isSetPort();
+ case HOLD_TIME:
+ return isSetHoldTime();
+ case KEEP_ALIVE_TIME:
+ return isSetKeepAliveTime();
+ case STALEPATH_TIME:
+ return isSetStalepathTime();
+ case ANNOUNCE_FBIT:
+ return isSetAnnounceFbit();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof startBgp_args)
+ return this.equals((startBgp_args)that);
+ return false;
+ }
+
+ public boolean equals(startBgp_args that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_asNumber = true;
+ boolean that_present_asNumber = true;
+ if (this_present_asNumber || that_present_asNumber) {
+ if (!(this_present_asNumber && that_present_asNumber))
+ return false;
+ if (this.asNumber != that.asNumber)
+ return false;
+ }
+
+ boolean this_present_routerId = true && this.isSetRouterId();
+ boolean that_present_routerId = true && that.isSetRouterId();
+ if (this_present_routerId || that_present_routerId) {
+ if (!(this_present_routerId && that_present_routerId))
+ return false;
+ if (!this.routerId.equals(that.routerId))
+ return false;
+ }
+
+ boolean this_present_port = true;
+ boolean that_present_port = true;
+ if (this_present_port || that_present_port) {
+ if (!(this_present_port && that_present_port))
+ return false;
+ if (this.port != that.port)
+ return false;
+ }
+
+ boolean this_present_holdTime = true;
+ boolean that_present_holdTime = true;
+ if (this_present_holdTime || that_present_holdTime) {
+ if (!(this_present_holdTime && that_present_holdTime))
+ return false;
+ if (this.holdTime != that.holdTime)
+ return false;
+ }
+
+ boolean this_present_keepAliveTime = true;
+ boolean that_present_keepAliveTime = true;
+ if (this_present_keepAliveTime || that_present_keepAliveTime) {
+ if (!(this_present_keepAliveTime && that_present_keepAliveTime))
+ return false;
+ if (this.keepAliveTime != that.keepAliveTime)
+ return false;
+ }
+
+ boolean this_present_stalepathTime = true;
+ boolean that_present_stalepathTime = true;
+ if (this_present_stalepathTime || that_present_stalepathTime) {
+ if (!(this_present_stalepathTime && that_present_stalepathTime))
+ return false;
+ if (this.stalepathTime != that.stalepathTime)
+ return false;
+ }
+
+ boolean this_present_announceFbit = true;
+ boolean that_present_announceFbit = true;
+ if (this_present_announceFbit || that_present_announceFbit) {
+ if (!(this_present_announceFbit && that_present_announceFbit))
+ return false;
+ if (this.announceFbit != that.announceFbit)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(startBgp_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetAsNumber()).compareTo(other.isSetAsNumber());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetAsNumber()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.asNumber, other.asNumber);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetRouterId()).compareTo(other.isSetRouterId());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetRouterId()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.routerId, other.routerId);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetPort()).compareTo(other.isSetPort());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetPort()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.port, other.port);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetHoldTime()).compareTo(other.isSetHoldTime());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetHoldTime()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.holdTime, other.holdTime);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetKeepAliveTime()).compareTo(other.isSetKeepAliveTime());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetKeepAliveTime()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.keepAliveTime, other.keepAliveTime);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetStalepathTime()).compareTo(other.isSetStalepathTime());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetStalepathTime()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.stalepathTime, other.stalepathTime);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetAnnounceFbit()).compareTo(other.isSetAnnounceFbit());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetAnnounceFbit()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.announceFbit, other.announceFbit);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("startBgp_args(");
+ boolean first = true;
+
+ sb.append("asNumber:");
+ sb.append(this.asNumber);
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("routerId:");
+ if (this.routerId == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.routerId);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("port:");
+ sb.append(this.port);
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("holdTime:");
+ sb.append(this.holdTime);
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("keepAliveTime:");
+ sb.append(this.keepAliveTime);
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("stalepathTime:");
+ sb.append(this.stalepathTime);
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("announceFbit:");
+ sb.append(this.announceFbit);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class startBgp_argsStandardSchemeFactory implements SchemeFactory {
+ public startBgp_argsStandardScheme getScheme() {
+ return new startBgp_argsStandardScheme();
+ }
+ }
+
+ private static class startBgp_argsStandardScheme extends StandardScheme<startBgp_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, startBgp_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // AS_NUMBER
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.asNumber = iprot.readI32();
+ struct.setAsNumberIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 2: // ROUTER_ID
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.routerId = iprot.readString();
+ struct.setRouterIdIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 3: // PORT
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.port = iprot.readI32();
+ struct.setPortIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 4: // HOLD_TIME
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.holdTime = iprot.readI32();
+ struct.setHoldTimeIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 5: // KEEP_ALIVE_TIME
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.keepAliveTime = iprot.readI32();
+ struct.setKeepAliveTimeIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 6: // STALEPATH_TIME
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.stalepathTime = iprot.readI32();
+ struct.setStalepathTimeIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 7: // ANNOUNCE_FBIT
+ if (schemeField.type == org.apache.thrift.protocol.TType.BOOL) {
+ struct.announceFbit = iprot.readBool();
+ struct.setAnnounceFbitIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, startBgp_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ oprot.writeFieldBegin(AS_NUMBER_FIELD_DESC);
+ oprot.writeI32(struct.asNumber);
+ oprot.writeFieldEnd();
+ if (struct.routerId != null) {
+ oprot.writeFieldBegin(ROUTER_ID_FIELD_DESC);
+ oprot.writeString(struct.routerId);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldBegin(PORT_FIELD_DESC);
+ oprot.writeI32(struct.port);
+ oprot.writeFieldEnd();
+ oprot.writeFieldBegin(HOLD_TIME_FIELD_DESC);
+ oprot.writeI32(struct.holdTime);
+ oprot.writeFieldEnd();
+ oprot.writeFieldBegin(KEEP_ALIVE_TIME_FIELD_DESC);
+ oprot.writeI32(struct.keepAliveTime);
+ oprot.writeFieldEnd();
+ oprot.writeFieldBegin(STALEPATH_TIME_FIELD_DESC);
+ oprot.writeI32(struct.stalepathTime);
+ oprot.writeFieldEnd();
+ oprot.writeFieldBegin(ANNOUNCE_FBIT_FIELD_DESC);
+ oprot.writeBool(struct.announceFbit);
+ oprot.writeFieldEnd();
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class startBgp_argsTupleSchemeFactory implements SchemeFactory {
+ public startBgp_argsTupleScheme getScheme() {
+ return new startBgp_argsTupleScheme();
+ }
+ }
+
+ private static class startBgp_argsTupleScheme extends TupleScheme<startBgp_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, startBgp_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetAsNumber()) {
+ optionals.set(0);
+ }
+ if (struct.isSetRouterId()) {
+ optionals.set(1);
+ }
+ if (struct.isSetPort()) {
+ optionals.set(2);
+ }
+ if (struct.isSetHoldTime()) {
+ optionals.set(3);
+ }
+ if (struct.isSetKeepAliveTime()) {
+ optionals.set(4);
+ }
+ if (struct.isSetStalepathTime()) {
+ optionals.set(5);
+ }
+ if (struct.isSetAnnounceFbit()) {
+ optionals.set(6);
+ }
+ oprot.writeBitSet(optionals, 7);
+ if (struct.isSetAsNumber()) {
+ oprot.writeI32(struct.asNumber);
+ }
+ if (struct.isSetRouterId()) {
+ oprot.writeString(struct.routerId);
+ }
+ if (struct.isSetPort()) {
+ oprot.writeI32(struct.port);
+ }
+ if (struct.isSetHoldTime()) {
+ oprot.writeI32(struct.holdTime);
+ }
+ if (struct.isSetKeepAliveTime()) {
+ oprot.writeI32(struct.keepAliveTime);
+ }
+ if (struct.isSetStalepathTime()) {
+ oprot.writeI32(struct.stalepathTime);
+ }
+ if (struct.isSetAnnounceFbit()) {
+ oprot.writeBool(struct.announceFbit);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, startBgp_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(7);
+ if (incoming.get(0)) {
+ struct.asNumber = iprot.readI32();
+ struct.setAsNumberIsSet(true);
+ }
+ if (incoming.get(1)) {
+ struct.routerId = iprot.readString();
+ struct.setRouterIdIsSet(true);
+ }
+ if (incoming.get(2)) {
+ struct.port = iprot.readI32();
+ struct.setPortIsSet(true);
+ }
+ if (incoming.get(3)) {
+ struct.holdTime = iprot.readI32();
+ struct.setHoldTimeIsSet(true);
+ }
+ if (incoming.get(4)) {
+ struct.keepAliveTime = iprot.readI32();
+ struct.setKeepAliveTimeIsSet(true);
+ }
+ if (incoming.get(5)) {
+ struct.stalepathTime = iprot.readI32();
+ struct.setStalepathTimeIsSet(true);
+ }
+ if (incoming.get(6)) {
+ struct.announceFbit = iprot.readBool();
+ struct.setAnnounceFbitIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class startBgp_result implements org.apache.thrift.TBase<startBgp_result, startBgp_result._Fields>, java.io.Serializable, Cloneable, Comparable<startBgp_result> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("startBgp_result");
+
+ private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new startBgp_resultStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new startBgp_resultTupleSchemeFactory());
+ }
+
+ public int success; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ SUCCESS((short)0, "success");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 0: // SUCCESS
+ return SUCCESS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __SUCCESS_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(startBgp_result.class, metaDataMap);
+ }
+
+ public startBgp_result() {
+ }
+
+ public startBgp_result(
+ int success)
+ {
+ this();
+ this.success = success;
+ setSuccessIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public startBgp_result(startBgp_result other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.success = other.success;
+ }
+
+ public startBgp_result deepCopy() {
+ return new startBgp_result(this);
+ }
+
+ @Override
+ public void clear() {
+ setSuccessIsSet(false);
+ this.success = 0;
+ }
+
+ public int getSuccess() {
+ return this.success;
+ }
+
+ public startBgp_result setSuccess(int success) {
+ this.success = success;
+ setSuccessIsSet(true);
+ return this;
+ }
+
+ public void unsetSuccess() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ /** Returns true if field success is set (has been assigned a value) and false otherwise */
+ public boolean isSetSuccess() {
+ return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ public void setSuccessIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case SUCCESS:
+ if (value == null) {
+ unsetSuccess();
+ } else {
+ setSuccess((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case SUCCESS:
+ return Integer.valueOf(getSuccess());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case SUCCESS:
+ return isSetSuccess();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof startBgp_result)
+ return this.equals((startBgp_result)that);
+ return false;
+ }
+
+ public boolean equals(startBgp_result that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_success = true;
+ boolean that_present_success = true;
+ if (this_present_success || that_present_success) {
+ if (!(this_present_success && that_present_success))
+ return false;
+ if (this.success != that.success)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(startBgp_result other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSuccess()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("startBgp_result(");
+ boolean first = true;
+
+ sb.append("success:");
+ sb.append(this.success);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class startBgp_resultStandardSchemeFactory implements SchemeFactory {
+ public startBgp_resultStandardScheme getScheme() {
+ return new startBgp_resultStandardScheme();
+ }
+ }
+
+ private static class startBgp_resultStandardScheme extends StandardScheme<startBgp_result> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, startBgp_result struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 0: // SUCCESS
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, startBgp_result struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.isSetSuccess()) {
+ oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+ oprot.writeI32(struct.success);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class startBgp_resultTupleSchemeFactory implements SchemeFactory {
+ public startBgp_resultTupleScheme getScheme() {
+ return new startBgp_resultTupleScheme();
+ }
+ }
+
+ private static class startBgp_resultTupleScheme extends TupleScheme<startBgp_result> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, startBgp_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetSuccess()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetSuccess()) {
+ oprot.writeI32(struct.success);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, startBgp_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class stopBgp_args implements org.apache.thrift.TBase<stopBgp_args, stopBgp_args._Fields>, java.io.Serializable, Cloneable, Comparable<stopBgp_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("stopBgp_args");
+
+ private static final org.apache.thrift.protocol.TField AS_NUMBER_FIELD_DESC = new org.apache.thrift.protocol.TField("asNumber", org.apache.thrift.protocol.TType.I32, (short)1);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new stopBgp_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new stopBgp_argsTupleSchemeFactory());
+ }
+
+ public int asNumber; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ AS_NUMBER((short)1, "asNumber");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // AS_NUMBER
+ return AS_NUMBER;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __ASNUMBER_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.AS_NUMBER, new org.apache.thrift.meta_data.FieldMetaData("asNumber", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(stopBgp_args.class, metaDataMap);
+ }
+
+ public stopBgp_args() {
+ }
+
+ public stopBgp_args(
+ int asNumber)
+ {
+ this();
+ this.asNumber = asNumber;
+ setAsNumberIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public stopBgp_args(stopBgp_args other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.asNumber = other.asNumber;
+ }
+
+ public stopBgp_args deepCopy() {
+ return new stopBgp_args(this);
+ }
+
+ @Override
+ public void clear() {
+ setAsNumberIsSet(false);
+ this.asNumber = 0;
+ }
+
+ public int getAsNumber() {
+ return this.asNumber;
+ }
+
+ public stopBgp_args setAsNumber(int asNumber) {
+ this.asNumber = asNumber;
+ setAsNumberIsSet(true);
+ return this;
+ }
+
+ public void unsetAsNumber() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __ASNUMBER_ISSET_ID);
+ }
+
+ /** Returns true if field asNumber is set (has been assigned a value) and false otherwise */
+ public boolean isSetAsNumber() {
+ return EncodingUtils.testBit(__isset_bitfield, __ASNUMBER_ISSET_ID);
+ }
+
+ public void setAsNumberIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __ASNUMBER_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case AS_NUMBER:
+ if (value == null) {
+ unsetAsNumber();
+ } else {
+ setAsNumber((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case AS_NUMBER:
+ return Integer.valueOf(getAsNumber());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case AS_NUMBER:
+ return isSetAsNumber();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof stopBgp_args)
+ return this.equals((stopBgp_args)that);
+ return false;
+ }
+
+ public boolean equals(stopBgp_args that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_asNumber = true;
+ boolean that_present_asNumber = true;
+ if (this_present_asNumber || that_present_asNumber) {
+ if (!(this_present_asNumber && that_present_asNumber))
+ return false;
+ if (this.asNumber != that.asNumber)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(stopBgp_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetAsNumber()).compareTo(other.isSetAsNumber());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetAsNumber()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.asNumber, other.asNumber);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("stopBgp_args(");
+ boolean first = true;
+
+ sb.append("asNumber:");
+ sb.append(this.asNumber);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class stopBgp_argsStandardSchemeFactory implements SchemeFactory {
+ public stopBgp_argsStandardScheme getScheme() {
+ return new stopBgp_argsStandardScheme();
+ }
+ }
+
+ private static class stopBgp_argsStandardScheme extends StandardScheme<stopBgp_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, stopBgp_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // AS_NUMBER
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.asNumber = iprot.readI32();
+ struct.setAsNumberIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, stopBgp_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ oprot.writeFieldBegin(AS_NUMBER_FIELD_DESC);
+ oprot.writeI32(struct.asNumber);
+ oprot.writeFieldEnd();
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class stopBgp_argsTupleSchemeFactory implements SchemeFactory {
+ public stopBgp_argsTupleScheme getScheme() {
+ return new stopBgp_argsTupleScheme();
+ }
+ }
+
+ private static class stopBgp_argsTupleScheme extends TupleScheme<stopBgp_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, stopBgp_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetAsNumber()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetAsNumber()) {
+ oprot.writeI32(struct.asNumber);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, stopBgp_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.asNumber = iprot.readI32();
+ struct.setAsNumberIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class stopBgp_result implements org.apache.thrift.TBase<stopBgp_result, stopBgp_result._Fields>, java.io.Serializable, Cloneable, Comparable<stopBgp_result> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("stopBgp_result");
+
+ private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new stopBgp_resultStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new stopBgp_resultTupleSchemeFactory());
+ }
+
+ public int success; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ SUCCESS((short)0, "success");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 0: // SUCCESS
+ return SUCCESS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __SUCCESS_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(stopBgp_result.class, metaDataMap);
+ }
+
+ public stopBgp_result() {
+ }
+
+ public stopBgp_result(
+ int success)
+ {
+ this();
+ this.success = success;
+ setSuccessIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public stopBgp_result(stopBgp_result other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.success = other.success;
+ }
+
+ public stopBgp_result deepCopy() {
+ return new stopBgp_result(this);
+ }
+
+ @Override
+ public void clear() {
+ setSuccessIsSet(false);
+ this.success = 0;
+ }
+
+ public int getSuccess() {
+ return this.success;
+ }
+
+ public stopBgp_result setSuccess(int success) {
+ this.success = success;
+ setSuccessIsSet(true);
+ return this;
+ }
+
+ public void unsetSuccess() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ /** Returns true if field success is set (has been assigned a value) and false otherwise */
+ public boolean isSetSuccess() {
+ return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ public void setSuccessIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case SUCCESS:
+ if (value == null) {
+ unsetSuccess();
+ } else {
+ setSuccess((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case SUCCESS:
+ return Integer.valueOf(getSuccess());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case SUCCESS:
+ return isSetSuccess();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof stopBgp_result)
+ return this.equals((stopBgp_result)that);
+ return false;
+ }
+
+ public boolean equals(stopBgp_result that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_success = true;
+ boolean that_present_success = true;
+ if (this_present_success || that_present_success) {
+ if (!(this_present_success && that_present_success))
+ return false;
+ if (this.success != that.success)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(stopBgp_result other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSuccess()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("stopBgp_result(");
+ boolean first = true;
+
+ sb.append("success:");
+ sb.append(this.success);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class stopBgp_resultStandardSchemeFactory implements SchemeFactory {
+ public stopBgp_resultStandardScheme getScheme() {
+ return new stopBgp_resultStandardScheme();
+ }
+ }
+
+ private static class stopBgp_resultStandardScheme extends StandardScheme<stopBgp_result> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, stopBgp_result struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 0: // SUCCESS
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, stopBgp_result struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.isSetSuccess()) {
+ oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+ oprot.writeI32(struct.success);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class stopBgp_resultTupleSchemeFactory implements SchemeFactory {
+ public stopBgp_resultTupleScheme getScheme() {
+ return new stopBgp_resultTupleScheme();
+ }
+ }
+
+ private static class stopBgp_resultTupleScheme extends TupleScheme<stopBgp_result> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, stopBgp_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetSuccess()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetSuccess()) {
+ oprot.writeI32(struct.success);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, stopBgp_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class createPeer_args implements org.apache.thrift.TBase<createPeer_args, createPeer_args._Fields>, java.io.Serializable, Cloneable, Comparable<createPeer_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("createPeer_args");
+
+ private static final org.apache.thrift.protocol.TField IP_ADDRESS_FIELD_DESC = new org.apache.thrift.protocol.TField("ipAddress", org.apache.thrift.protocol.TType.STRING, (short)1);
+ private static final org.apache.thrift.protocol.TField AS_NUMBER_FIELD_DESC = new org.apache.thrift.protocol.TField("asNumber", org.apache.thrift.protocol.TType.I32, (short)2);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new createPeer_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new createPeer_argsTupleSchemeFactory());
+ }
+
+ public String ipAddress; // required
+ public int asNumber; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ IP_ADDRESS((short)1, "ipAddress"),
+ AS_NUMBER((short)2, "asNumber");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // IP_ADDRESS
+ return IP_ADDRESS;
+ case 2: // AS_NUMBER
+ return AS_NUMBER;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __ASNUMBER_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.IP_ADDRESS, new org.apache.thrift.meta_data.FieldMetaData("ipAddress", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ tmpMap.put(_Fields.AS_NUMBER, new org.apache.thrift.meta_data.FieldMetaData("asNumber", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(createPeer_args.class, metaDataMap);
+ }
+
+ public createPeer_args() {
+ }
+
+ public createPeer_args(
+ String ipAddress,
+ int asNumber)
+ {
+ this();
+ this.ipAddress = ipAddress;
+ this.asNumber = asNumber;
+ setAsNumberIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public createPeer_args(createPeer_args other) {
+ __isset_bitfield = other.__isset_bitfield;
+ if (other.isSetIpAddress()) {
+ this.ipAddress = other.ipAddress;
+ }
+ this.asNumber = other.asNumber;
+ }
+
+ public createPeer_args deepCopy() {
+ return new createPeer_args(this);
+ }
+
+ @Override
+ public void clear() {
+ this.ipAddress = null;
+ setAsNumberIsSet(false);
+ this.asNumber = 0;
+ }
+
+ public String getIpAddress() {
+ return this.ipAddress;
+ }
+
+ public createPeer_args setIpAddress(String ipAddress) {
+ this.ipAddress = ipAddress;
+ return this;
+ }
+
+ public void unsetIpAddress() {
+ this.ipAddress = null;
+ }
+
+ /** Returns true if field ipAddress is set (has been assigned a value) and false otherwise */
+ public boolean isSetIpAddress() {
+ return this.ipAddress != null;
+ }
+
+ public void setIpAddressIsSet(boolean value) {
+ if (!value) {
+ this.ipAddress = null;
+ }
+ }
+
+ public int getAsNumber() {
+ return this.asNumber;
+ }
+
+ public createPeer_args setAsNumber(int asNumber) {
+ this.asNumber = asNumber;
+ setAsNumberIsSet(true);
+ return this;
+ }
+
+ public void unsetAsNumber() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __ASNUMBER_ISSET_ID);
+ }
+
+ /** Returns true if field asNumber is set (has been assigned a value) and false otherwise */
+ public boolean isSetAsNumber() {
+ return EncodingUtils.testBit(__isset_bitfield, __ASNUMBER_ISSET_ID);
+ }
+
+ public void setAsNumberIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __ASNUMBER_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case IP_ADDRESS:
+ if (value == null) {
+ unsetIpAddress();
+ } else {
+ setIpAddress((String)value);
+ }
+ break;
+
+ case AS_NUMBER:
+ if (value == null) {
+ unsetAsNumber();
+ } else {
+ setAsNumber((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case IP_ADDRESS:
+ return getIpAddress();
+
+ case AS_NUMBER:
+ return Integer.valueOf(getAsNumber());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case IP_ADDRESS:
+ return isSetIpAddress();
+ case AS_NUMBER:
+ return isSetAsNumber();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof createPeer_args)
+ return this.equals((createPeer_args)that);
+ return false;
+ }
+
+ public boolean equals(createPeer_args that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_ipAddress = true && this.isSetIpAddress();
+ boolean that_present_ipAddress = true && that.isSetIpAddress();
+ if (this_present_ipAddress || that_present_ipAddress) {
+ if (!(this_present_ipAddress && that_present_ipAddress))
+ return false;
+ if (!this.ipAddress.equals(that.ipAddress))
+ return false;
+ }
+
+ boolean this_present_asNumber = true;
+ boolean that_present_asNumber = true;
+ if (this_present_asNumber || that_present_asNumber) {
+ if (!(this_present_asNumber && that_present_asNumber))
+ return false;
+ if (this.asNumber != that.asNumber)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(createPeer_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetIpAddress()).compareTo(other.isSetIpAddress());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetIpAddress()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.ipAddress, other.ipAddress);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetAsNumber()).compareTo(other.isSetAsNumber());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetAsNumber()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.asNumber, other.asNumber);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("createPeer_args(");
+ boolean first = true;
+
+ sb.append("ipAddress:");
+ if (this.ipAddress == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.ipAddress);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("asNumber:");
+ sb.append(this.asNumber);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class createPeer_argsStandardSchemeFactory implements SchemeFactory {
+ public createPeer_argsStandardScheme getScheme() {
+ return new createPeer_argsStandardScheme();
+ }
+ }
+
+ private static class createPeer_argsStandardScheme extends StandardScheme<createPeer_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, createPeer_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // IP_ADDRESS
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.ipAddress = iprot.readString();
+ struct.setIpAddressIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 2: // AS_NUMBER
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.asNumber = iprot.readI32();
+ struct.setAsNumberIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, createPeer_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.ipAddress != null) {
+ oprot.writeFieldBegin(IP_ADDRESS_FIELD_DESC);
+ oprot.writeString(struct.ipAddress);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldBegin(AS_NUMBER_FIELD_DESC);
+ oprot.writeI32(struct.asNumber);
+ oprot.writeFieldEnd();
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class createPeer_argsTupleSchemeFactory implements SchemeFactory {
+ public createPeer_argsTupleScheme getScheme() {
+ return new createPeer_argsTupleScheme();
+ }
+ }
+
+ private static class createPeer_argsTupleScheme extends TupleScheme<createPeer_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, createPeer_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetIpAddress()) {
+ optionals.set(0);
+ }
+ if (struct.isSetAsNumber()) {
+ optionals.set(1);
+ }
+ oprot.writeBitSet(optionals, 2);
+ if (struct.isSetIpAddress()) {
+ oprot.writeString(struct.ipAddress);
+ }
+ if (struct.isSetAsNumber()) {
+ oprot.writeI32(struct.asNumber);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, createPeer_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(2);
+ if (incoming.get(0)) {
+ struct.ipAddress = iprot.readString();
+ struct.setIpAddressIsSet(true);
+ }
+ if (incoming.get(1)) {
+ struct.asNumber = iprot.readI32();
+ struct.setAsNumberIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class createPeer_result implements org.apache.thrift.TBase<createPeer_result, createPeer_result._Fields>, java.io.Serializable, Cloneable, Comparable<createPeer_result> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("createPeer_result");
+
+ private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new createPeer_resultStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new createPeer_resultTupleSchemeFactory());
+ }
+
+ public int success; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ SUCCESS((short)0, "success");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 0: // SUCCESS
+ return SUCCESS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __SUCCESS_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(createPeer_result.class, metaDataMap);
+ }
+
+ public createPeer_result() {
+ }
+
+ public createPeer_result(
+ int success)
+ {
+ this();
+ this.success = success;
+ setSuccessIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public createPeer_result(createPeer_result other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.success = other.success;
+ }
+
+ public createPeer_result deepCopy() {
+ return new createPeer_result(this);
+ }
+
+ @Override
+ public void clear() {
+ setSuccessIsSet(false);
+ this.success = 0;
+ }
+
+ public int getSuccess() {
+ return this.success;
+ }
+
+ public createPeer_result setSuccess(int success) {
+ this.success = success;
+ setSuccessIsSet(true);
+ return this;
+ }
+
+ public void unsetSuccess() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ /** Returns true if field success is set (has been assigned a value) and false otherwise */
+ public boolean isSetSuccess() {
+ return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ public void setSuccessIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case SUCCESS:
+ if (value == null) {
+ unsetSuccess();
+ } else {
+ setSuccess((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case SUCCESS:
+ return Integer.valueOf(getSuccess());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case SUCCESS:
+ return isSetSuccess();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof createPeer_result)
+ return this.equals((createPeer_result)that);
+ return false;
+ }
+
+ public boolean equals(createPeer_result that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_success = true;
+ boolean that_present_success = true;
+ if (this_present_success || that_present_success) {
+ if (!(this_present_success && that_present_success))
+ return false;
+ if (this.success != that.success)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(createPeer_result other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSuccess()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("createPeer_result(");
+ boolean first = true;
+
+ sb.append("success:");
+ sb.append(this.success);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class createPeer_resultStandardSchemeFactory implements SchemeFactory {
+ public createPeer_resultStandardScheme getScheme() {
+ return new createPeer_resultStandardScheme();
+ }
+ }
+
+ private static class createPeer_resultStandardScheme extends StandardScheme<createPeer_result> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, createPeer_result struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 0: // SUCCESS
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, createPeer_result struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.isSetSuccess()) {
+ oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+ oprot.writeI32(struct.success);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class createPeer_resultTupleSchemeFactory implements SchemeFactory {
+ public createPeer_resultTupleScheme getScheme() {
+ return new createPeer_resultTupleScheme();
+ }
+ }
+
+ private static class createPeer_resultTupleScheme extends TupleScheme<createPeer_result> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, createPeer_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetSuccess()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetSuccess()) {
+ oprot.writeI32(struct.success);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, createPeer_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class deletePeer_args implements org.apache.thrift.TBase<deletePeer_args, deletePeer_args._Fields>, java.io.Serializable, Cloneable, Comparable<deletePeer_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("deletePeer_args");
+
+ private static final org.apache.thrift.protocol.TField IP_ADDRESS_FIELD_DESC = new org.apache.thrift.protocol.TField("ipAddress", org.apache.thrift.protocol.TType.STRING, (short)1);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new deletePeer_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new deletePeer_argsTupleSchemeFactory());
+ }
+
+ public String ipAddress; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ IP_ADDRESS((short)1, "ipAddress");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // IP_ADDRESS
+ return IP_ADDRESS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.IP_ADDRESS, new org.apache.thrift.meta_data.FieldMetaData("ipAddress", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(deletePeer_args.class, metaDataMap);
+ }
+
+ public deletePeer_args() {
+ }
+
+ public deletePeer_args(
+ String ipAddress)
+ {
+ this();
+ this.ipAddress = ipAddress;
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public deletePeer_args(deletePeer_args other) {
+ if (other.isSetIpAddress()) {
+ this.ipAddress = other.ipAddress;
+ }
+ }
+
+ public deletePeer_args deepCopy() {
+ return new deletePeer_args(this);
+ }
+
+ @Override
+ public void clear() {
+ this.ipAddress = null;
+ }
+
+ public String getIpAddress() {
+ return this.ipAddress;
+ }
+
+ public deletePeer_args setIpAddress(String ipAddress) {
+ this.ipAddress = ipAddress;
+ return this;
+ }
+
+ public void unsetIpAddress() {
+ this.ipAddress = null;
+ }
+
+ /** Returns true if field ipAddress is set (has been assigned a value) and false otherwise */
+ public boolean isSetIpAddress() {
+ return this.ipAddress != null;
+ }
+
+ public void setIpAddressIsSet(boolean value) {
+ if (!value) {
+ this.ipAddress = null;
+ }
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case IP_ADDRESS:
+ if (value == null) {
+ unsetIpAddress();
+ } else {
+ setIpAddress((String)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case IP_ADDRESS:
+ return getIpAddress();
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case IP_ADDRESS:
+ return isSetIpAddress();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof deletePeer_args)
+ return this.equals((deletePeer_args)that);
+ return false;
+ }
+
+ public boolean equals(deletePeer_args that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_ipAddress = true && this.isSetIpAddress();
+ boolean that_present_ipAddress = true && that.isSetIpAddress();
+ if (this_present_ipAddress || that_present_ipAddress) {
+ if (!(this_present_ipAddress && that_present_ipAddress))
+ return false;
+ if (!this.ipAddress.equals(that.ipAddress))
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(deletePeer_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetIpAddress()).compareTo(other.isSetIpAddress());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetIpAddress()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.ipAddress, other.ipAddress);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("deletePeer_args(");
+ boolean first = true;
+
+ sb.append("ipAddress:");
+ if (this.ipAddress == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.ipAddress);
+ }
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class deletePeer_argsStandardSchemeFactory implements SchemeFactory {
+ public deletePeer_argsStandardScheme getScheme() {
+ return new deletePeer_argsStandardScheme();
+ }
+ }
+
+ private static class deletePeer_argsStandardScheme extends StandardScheme<deletePeer_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, deletePeer_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // IP_ADDRESS
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.ipAddress = iprot.readString();
+ struct.setIpAddressIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, deletePeer_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.ipAddress != null) {
+ oprot.writeFieldBegin(IP_ADDRESS_FIELD_DESC);
+ oprot.writeString(struct.ipAddress);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class deletePeer_argsTupleSchemeFactory implements SchemeFactory {
+ public deletePeer_argsTupleScheme getScheme() {
+ return new deletePeer_argsTupleScheme();
+ }
+ }
+
+ private static class deletePeer_argsTupleScheme extends TupleScheme<deletePeer_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, deletePeer_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetIpAddress()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetIpAddress()) {
+ oprot.writeString(struct.ipAddress);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, deletePeer_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.ipAddress = iprot.readString();
+ struct.setIpAddressIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class deletePeer_result implements org.apache.thrift.TBase<deletePeer_result, deletePeer_result._Fields>, java.io.Serializable, Cloneable, Comparable<deletePeer_result> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("deletePeer_result");
+
+ private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new deletePeer_resultStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new deletePeer_resultTupleSchemeFactory());
+ }
+
+ public int success; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ SUCCESS((short)0, "success");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 0: // SUCCESS
+ return SUCCESS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __SUCCESS_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(deletePeer_result.class, metaDataMap);
+ }
+
+ public deletePeer_result() {
+ }
+
+ public deletePeer_result(
+ int success)
+ {
+ this();
+ this.success = success;
+ setSuccessIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public deletePeer_result(deletePeer_result other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.success = other.success;
+ }
+
+ public deletePeer_result deepCopy() {
+ return new deletePeer_result(this);
+ }
+
+ @Override
+ public void clear() {
+ setSuccessIsSet(false);
+ this.success = 0;
+ }
+
+ public int getSuccess() {
+ return this.success;
+ }
+
+ public deletePeer_result setSuccess(int success) {
+ this.success = success;
+ setSuccessIsSet(true);
+ return this;
+ }
+
+ public void unsetSuccess() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ /** Returns true if field success is set (has been assigned a value) and false otherwise */
+ public boolean isSetSuccess() {
+ return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ public void setSuccessIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case SUCCESS:
+ if (value == null) {
+ unsetSuccess();
+ } else {
+ setSuccess((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case SUCCESS:
+ return Integer.valueOf(getSuccess());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case SUCCESS:
+ return isSetSuccess();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof deletePeer_result)
+ return this.equals((deletePeer_result)that);
+ return false;
+ }
+
+ public boolean equals(deletePeer_result that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_success = true;
+ boolean that_present_success = true;
+ if (this_present_success || that_present_success) {
+ if (!(this_present_success && that_present_success))
+ return false;
+ if (this.success != that.success)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(deletePeer_result other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSuccess()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("deletePeer_result(");
+ boolean first = true;
+
+ sb.append("success:");
+ sb.append(this.success);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class deletePeer_resultStandardSchemeFactory implements SchemeFactory {
+ public deletePeer_resultStandardScheme getScheme() {
+ return new deletePeer_resultStandardScheme();
+ }
+ }
+
+ private static class deletePeer_resultStandardScheme extends StandardScheme<deletePeer_result> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, deletePeer_result struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 0: // SUCCESS
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, deletePeer_result struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.isSetSuccess()) {
+ oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+ oprot.writeI32(struct.success);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class deletePeer_resultTupleSchemeFactory implements SchemeFactory {
+ public deletePeer_resultTupleScheme getScheme() {
+ return new deletePeer_resultTupleScheme();
+ }
+ }
+
+ private static class deletePeer_resultTupleScheme extends TupleScheme<deletePeer_result> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, deletePeer_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetSuccess()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetSuccess()) {
+ oprot.writeI32(struct.success);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, deletePeer_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class addVrf_args implements org.apache.thrift.TBase<addVrf_args, addVrf_args._Fields>, java.io.Serializable, Cloneable, Comparable<addVrf_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("addVrf_args");
+
+ private static final org.apache.thrift.protocol.TField RD_FIELD_DESC = new org.apache.thrift.protocol.TField("rd", org.apache.thrift.protocol.TType.STRING, (short)1);
+ private static final org.apache.thrift.protocol.TField IRTS_FIELD_DESC = new org.apache.thrift.protocol.TField("irts", org.apache.thrift.protocol.TType.LIST, (short)2);
+ private static final org.apache.thrift.protocol.TField ERTS_FIELD_DESC = new org.apache.thrift.protocol.TField("erts", org.apache.thrift.protocol.TType.LIST, (short)3);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new addVrf_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new addVrf_argsTupleSchemeFactory());
+ }
+
+ public String rd; // required
+ public List<String> irts; // required
+ public List<String> erts; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ RD((short)1, "rd"),
+ IRTS((short)2, "irts"),
+ ERTS((short)3, "erts");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // RD
+ return RD;
+ case 2: // IRTS
+ return IRTS;
+ case 3: // ERTS
+ return ERTS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.RD, new org.apache.thrift.meta_data.FieldMetaData("rd", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ tmpMap.put(_Fields.IRTS, new org.apache.thrift.meta_data.FieldMetaData("irts", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
+ tmpMap.put(_Fields.ERTS, new org.apache.thrift.meta_data.FieldMetaData("erts", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(addVrf_args.class, metaDataMap);
+ }
+
+ public addVrf_args() {
+ }
+
+ public addVrf_args(
+ String rd,
+ List<String> irts,
+ List<String> erts)
+ {
+ this();
+ this.rd = rd;
+ this.irts = irts;
+ this.erts = erts;
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public addVrf_args(addVrf_args other) {
+ if (other.isSetRd()) {
+ this.rd = other.rd;
+ }
+ if (other.isSetIrts()) {
+ List<String> __this__irts = new ArrayList<String>(other.irts);
+ this.irts = __this__irts;
+ }
+ if (other.isSetErts()) {
+ List<String> __this__erts = new ArrayList<String>(other.erts);
+ this.erts = __this__erts;
+ }
+ }
+
+ public addVrf_args deepCopy() {
+ return new addVrf_args(this);
+ }
+
+ @Override
+ public void clear() {
+ this.rd = null;
+ this.irts = null;
+ this.erts = null;
+ }
+
+ public String getRd() {
+ return this.rd;
+ }
+
+ public addVrf_args setRd(String rd) {
+ this.rd = rd;
+ return this;
+ }
+
+ public void unsetRd() {
+ this.rd = null;
+ }
+
+ /** Returns true if field rd is set (has been assigned a value) and false otherwise */
+ public boolean isSetRd() {
+ return this.rd != null;
+ }
+
+ public void setRdIsSet(boolean value) {
+ if (!value) {
+ this.rd = null;
+ }
+ }
+
+ public int getIrtsSize() {
+ return (this.irts == null) ? 0 : this.irts.size();
+ }
+
+ public java.util.Iterator<String> getIrtsIterator() {
+ return (this.irts == null) ? null : this.irts.iterator();
+ }
+
+ public void addToIrts(String elem) {
+ if (this.irts == null) {
+ this.irts = new ArrayList<String>();
+ }
+ this.irts.add(elem);
+ }
+
+ public List<String> getIrts() {
+ return this.irts;
+ }
+
+ public addVrf_args setIrts(List<String> irts) {
+ this.irts = irts;
+ return this;
+ }
+
+ public void unsetIrts() {
+ this.irts = null;
+ }
+
+ /** Returns true if field irts is set (has been assigned a value) and false otherwise */
+ public boolean isSetIrts() {
+ return this.irts != null;
+ }
+
+ public void setIrtsIsSet(boolean value) {
+ if (!value) {
+ this.irts = null;
+ }
+ }
+
+ public int getErtsSize() {
+ return (this.erts == null) ? 0 : this.erts.size();
+ }
+
+ public java.util.Iterator<String> getErtsIterator() {
+ return (this.erts == null) ? null : this.erts.iterator();
+ }
+
+ public void addToErts(String elem) {
+ if (this.erts == null) {
+ this.erts = new ArrayList<String>();
+ }
+ this.erts.add(elem);
+ }
+
+ public List<String> getErts() {
+ return this.erts;
+ }
+
+ public addVrf_args setErts(List<String> erts) {
+ this.erts = erts;
+ return this;
+ }
+
+ public void unsetErts() {
+ this.erts = null;
+ }
+
+ /** Returns true if field erts is set (has been assigned a value) and false otherwise */
+ public boolean isSetErts() {
+ return this.erts != null;
+ }
+
+ public void setErtsIsSet(boolean value) {
+ if (!value) {
+ this.erts = null;
+ }
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case RD:
+ if (value == null) {
+ unsetRd();
+ } else {
+ setRd((String)value);
+ }
+ break;
+
+ case IRTS:
+ if (value == null) {
+ unsetIrts();
+ } else {
+ setIrts((List<String>)value);
+ }
+ break;
+
+ case ERTS:
+ if (value == null) {
+ unsetErts();
+ } else {
+ setErts((List<String>)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case RD:
+ return getRd();
+
+ case IRTS:
+ return getIrts();
+
+ case ERTS:
+ return getErts();
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case RD:
+ return isSetRd();
+ case IRTS:
+ return isSetIrts();
+ case ERTS:
+ return isSetErts();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof addVrf_args)
+ return this.equals((addVrf_args)that);
+ return false;
+ }
+
+ public boolean equals(addVrf_args that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_rd = true && this.isSetRd();
+ boolean that_present_rd = true && that.isSetRd();
+ if (this_present_rd || that_present_rd) {
+ if (!(this_present_rd && that_present_rd))
+ return false;
+ if (!this.rd.equals(that.rd))
+ return false;
+ }
+
+ boolean this_present_irts = true && this.isSetIrts();
+ boolean that_present_irts = true && that.isSetIrts();
+ if (this_present_irts || that_present_irts) {
+ if (!(this_present_irts && that_present_irts))
+ return false;
+ if (!this.irts.equals(that.irts))
+ return false;
+ }
+
+ boolean this_present_erts = true && this.isSetErts();
+ boolean that_present_erts = true && that.isSetErts();
+ if (this_present_erts || that_present_erts) {
+ if (!(this_present_erts && that_present_erts))
+ return false;
+ if (!this.erts.equals(that.erts))
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(addVrf_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetRd()).compareTo(other.isSetRd());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetRd()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.rd, other.rd);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetIrts()).compareTo(other.isSetIrts());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetIrts()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.irts, other.irts);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetErts()).compareTo(other.isSetErts());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetErts()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.erts, other.erts);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("addVrf_args(");
+ boolean first = true;
+
+ sb.append("rd:");
+ if (this.rd == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.rd);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("irts:");
+ if (this.irts == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.irts);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("erts:");
+ if (this.erts == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.erts);
+ }
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class addVrf_argsStandardSchemeFactory implements SchemeFactory {
+ public addVrf_argsStandardScheme getScheme() {
+ return new addVrf_argsStandardScheme();
+ }
+ }
+
+ private static class addVrf_argsStandardScheme extends StandardScheme<addVrf_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, addVrf_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // RD
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.rd = iprot.readString();
+ struct.setRdIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 2: // IRTS
+ if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
+ {
+ org.apache.thrift.protocol.TList _list8 = iprot.readListBegin();
+ struct.irts = new ArrayList<String>(_list8.size);
+ for (int _i9 = 0; _i9 < _list8.size; ++_i9)
+ {
+ String _elem10;
+ _elem10 = iprot.readString();
+ struct.irts.add(_elem10);
+ }
+ iprot.readListEnd();
+ }
+ struct.setIrtsIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 3: // ERTS
+ if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
+ {
+ org.apache.thrift.protocol.TList _list11 = iprot.readListBegin();
+ struct.erts = new ArrayList<String>(_list11.size);
+ for (int _i12 = 0; _i12 < _list11.size; ++_i12)
+ {
+ String _elem13;
+ _elem13 = iprot.readString();
+ struct.erts.add(_elem13);
+ }
+ iprot.readListEnd();
+ }
+ struct.setErtsIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, addVrf_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.rd != null) {
+ oprot.writeFieldBegin(RD_FIELD_DESC);
+ oprot.writeString(struct.rd);
+ oprot.writeFieldEnd();
+ }
+ if (struct.irts != null) {
+ oprot.writeFieldBegin(IRTS_FIELD_DESC);
+ {
+ oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, struct.irts.size()));
+ for (String _iter14 : struct.irts)
+ {
+ oprot.writeString(_iter14);
+ }
+ oprot.writeListEnd();
+ }
+ oprot.writeFieldEnd();
+ }
+ if (struct.erts != null) {
+ oprot.writeFieldBegin(ERTS_FIELD_DESC);
+ {
+ oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, struct.erts.size()));
+ for (String _iter15 : struct.erts)
+ {
+ oprot.writeString(_iter15);
+ }
+ oprot.writeListEnd();
+ }
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class addVrf_argsTupleSchemeFactory implements SchemeFactory {
+ public addVrf_argsTupleScheme getScheme() {
+ return new addVrf_argsTupleScheme();
+ }
+ }
+
+ private static class addVrf_argsTupleScheme extends TupleScheme<addVrf_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, addVrf_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetRd()) {
+ optionals.set(0);
+ }
+ if (struct.isSetIrts()) {
+ optionals.set(1);
+ }
+ if (struct.isSetErts()) {
+ optionals.set(2);
+ }
+ oprot.writeBitSet(optionals, 3);
+ if (struct.isSetRd()) {
+ oprot.writeString(struct.rd);
+ }
+ if (struct.isSetIrts()) {
+ {
+ oprot.writeI32(struct.irts.size());
+ for (String _iter16 : struct.irts)
+ {
+ oprot.writeString(_iter16);
+ }
+ }
+ }
+ if (struct.isSetErts()) {
+ {
+ oprot.writeI32(struct.erts.size());
+ for (String _iter17 : struct.erts)
+ {
+ oprot.writeString(_iter17);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, addVrf_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(3);
+ if (incoming.get(0)) {
+ struct.rd = iprot.readString();
+ struct.setRdIsSet(true);
+ }
+ if (incoming.get(1)) {
+ {
+ org.apache.thrift.protocol.TList _list18 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
+ struct.irts = new ArrayList<String>(_list18.size);
+ for (int _i19 = 0; _i19 < _list18.size; ++_i19)
+ {
+ String _elem20;
+ _elem20 = iprot.readString();
+ struct.irts.add(_elem20);
+ }
+ }
+ struct.setIrtsIsSet(true);
+ }
+ if (incoming.get(2)) {
+ {
+ org.apache.thrift.protocol.TList _list21 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRING, iprot.readI32());
+ struct.erts = new ArrayList<String>(_list21.size);
+ for (int _i22 = 0; _i22 < _list21.size; ++_i22)
+ {
+ String _elem23;
+ _elem23 = iprot.readString();
+ struct.erts.add(_elem23);
+ }
+ }
+ struct.setErtsIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class addVrf_result implements org.apache.thrift.TBase<addVrf_result, addVrf_result._Fields>, java.io.Serializable, Cloneable, Comparable<addVrf_result> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("addVrf_result");
+
+ private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new addVrf_resultStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new addVrf_resultTupleSchemeFactory());
+ }
+
+ public int success; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ SUCCESS((short)0, "success");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 0: // SUCCESS
+ return SUCCESS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __SUCCESS_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(addVrf_result.class, metaDataMap);
+ }
+
+ public addVrf_result() {
+ }
+
+ public addVrf_result(
+ int success)
+ {
+ this();
+ this.success = success;
+ setSuccessIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public addVrf_result(addVrf_result other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.success = other.success;
+ }
+
+ public addVrf_result deepCopy() {
+ return new addVrf_result(this);
+ }
+
+ @Override
+ public void clear() {
+ setSuccessIsSet(false);
+ this.success = 0;
+ }
+
+ public int getSuccess() {
+ return this.success;
+ }
+
+ public addVrf_result setSuccess(int success) {
+ this.success = success;
+ setSuccessIsSet(true);
+ return this;
+ }
+
+ public void unsetSuccess() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ /** Returns true if field success is set (has been assigned a value) and false otherwise */
+ public boolean isSetSuccess() {
+ return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ public void setSuccessIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case SUCCESS:
+ if (value == null) {
+ unsetSuccess();
+ } else {
+ setSuccess((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case SUCCESS:
+ return Integer.valueOf(getSuccess());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case SUCCESS:
+ return isSetSuccess();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof addVrf_result)
+ return this.equals((addVrf_result)that);
+ return false;
+ }
+
+ public boolean equals(addVrf_result that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_success = true;
+ boolean that_present_success = true;
+ if (this_present_success || that_present_success) {
+ if (!(this_present_success && that_present_success))
+ return false;
+ if (this.success != that.success)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(addVrf_result other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSuccess()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("addVrf_result(");
+ boolean first = true;
+
+ sb.append("success:");
+ sb.append(this.success);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class addVrf_resultStandardSchemeFactory implements SchemeFactory {
+ public addVrf_resultStandardScheme getScheme() {
+ return new addVrf_resultStandardScheme();
+ }
+ }
+
+ private static class addVrf_resultStandardScheme extends StandardScheme<addVrf_result> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, addVrf_result struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 0: // SUCCESS
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, addVrf_result struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.isSetSuccess()) {
+ oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+ oprot.writeI32(struct.success);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class addVrf_resultTupleSchemeFactory implements SchemeFactory {
+ public addVrf_resultTupleScheme getScheme() {
+ return new addVrf_resultTupleScheme();
+ }
+ }
+
+ private static class addVrf_resultTupleScheme extends TupleScheme<addVrf_result> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, addVrf_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetSuccess()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetSuccess()) {
+ oprot.writeI32(struct.success);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, addVrf_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class delVrf_args implements org.apache.thrift.TBase<delVrf_args, delVrf_args._Fields>, java.io.Serializable, Cloneable, Comparable<delVrf_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("delVrf_args");
+
+ private static final org.apache.thrift.protocol.TField RD_FIELD_DESC = new org.apache.thrift.protocol.TField("rd", org.apache.thrift.protocol.TType.STRING, (short)1);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new delVrf_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new delVrf_argsTupleSchemeFactory());
+ }
+
+ public String rd; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ RD((short)1, "rd");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // RD
+ return RD;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.RD, new org.apache.thrift.meta_data.FieldMetaData("rd", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(delVrf_args.class, metaDataMap);
+ }
+
+ public delVrf_args() {
+ }
+
+ public delVrf_args(
+ String rd)
+ {
+ this();
+ this.rd = rd;
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public delVrf_args(delVrf_args other) {
+ if (other.isSetRd()) {
+ this.rd = other.rd;
+ }
+ }
+
+ public delVrf_args deepCopy() {
+ return new delVrf_args(this);
+ }
+
+ @Override
+ public void clear() {
+ this.rd = null;
+ }
+
+ public String getRd() {
+ return this.rd;
+ }
+
+ public delVrf_args setRd(String rd) {
+ this.rd = rd;
+ return this;
+ }
+
+ public void unsetRd() {
+ this.rd = null;
+ }
+
+ /** Returns true if field rd is set (has been assigned a value) and false otherwise */
+ public boolean isSetRd() {
+ return this.rd != null;
+ }
+
+ public void setRdIsSet(boolean value) {
+ if (!value) {
+ this.rd = null;
+ }
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case RD:
+ if (value == null) {
+ unsetRd();
+ } else {
+ setRd((String)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case RD:
+ return getRd();
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case RD:
+ return isSetRd();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof delVrf_args)
+ return this.equals((delVrf_args)that);
+ return false;
+ }
+
+ public boolean equals(delVrf_args that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_rd = true && this.isSetRd();
+ boolean that_present_rd = true && that.isSetRd();
+ if (this_present_rd || that_present_rd) {
+ if (!(this_present_rd && that_present_rd))
+ return false;
+ if (!this.rd.equals(that.rd))
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(delVrf_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetRd()).compareTo(other.isSetRd());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetRd()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.rd, other.rd);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("delVrf_args(");
+ boolean first = true;
+
+ sb.append("rd:");
+ if (this.rd == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.rd);
+ }
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class delVrf_argsStandardSchemeFactory implements SchemeFactory {
+ public delVrf_argsStandardScheme getScheme() {
+ return new delVrf_argsStandardScheme();
+ }
+ }
+
+ private static class delVrf_argsStandardScheme extends StandardScheme<delVrf_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, delVrf_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // RD
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.rd = iprot.readString();
+ struct.setRdIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, delVrf_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.rd != null) {
+ oprot.writeFieldBegin(RD_FIELD_DESC);
+ oprot.writeString(struct.rd);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class delVrf_argsTupleSchemeFactory implements SchemeFactory {
+ public delVrf_argsTupleScheme getScheme() {
+ return new delVrf_argsTupleScheme();
+ }
+ }
+
+ private static class delVrf_argsTupleScheme extends TupleScheme<delVrf_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, delVrf_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetRd()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetRd()) {
+ oprot.writeString(struct.rd);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, delVrf_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.rd = iprot.readString();
+ struct.setRdIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class delVrf_result implements org.apache.thrift.TBase<delVrf_result, delVrf_result._Fields>, java.io.Serializable, Cloneable, Comparable<delVrf_result> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("delVrf_result");
+
+ private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new delVrf_resultStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new delVrf_resultTupleSchemeFactory());
+ }
+
+ public int success; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ SUCCESS((short)0, "success");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 0: // SUCCESS
+ return SUCCESS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __SUCCESS_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(delVrf_result.class, metaDataMap);
+ }
+
+ public delVrf_result() {
+ }
+
+ public delVrf_result(
+ int success)
+ {
+ this();
+ this.success = success;
+ setSuccessIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public delVrf_result(delVrf_result other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.success = other.success;
+ }
+
+ public delVrf_result deepCopy() {
+ return new delVrf_result(this);
+ }
+
+ @Override
+ public void clear() {
+ setSuccessIsSet(false);
+ this.success = 0;
+ }
+
+ public int getSuccess() {
+ return this.success;
+ }
+
+ public delVrf_result setSuccess(int success) {
+ this.success = success;
+ setSuccessIsSet(true);
+ return this;
+ }
+
+ public void unsetSuccess() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ /** Returns true if field success is set (has been assigned a value) and false otherwise */
+ public boolean isSetSuccess() {
+ return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ public void setSuccessIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case SUCCESS:
+ if (value == null) {
+ unsetSuccess();
+ } else {
+ setSuccess((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case SUCCESS:
+ return Integer.valueOf(getSuccess());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case SUCCESS:
+ return isSetSuccess();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof delVrf_result)
+ return this.equals((delVrf_result)that);
+ return false;
+ }
+
+ public boolean equals(delVrf_result that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_success = true;
+ boolean that_present_success = true;
+ if (this_present_success || that_present_success) {
+ if (!(this_present_success && that_present_success))
+ return false;
+ if (this.success != that.success)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(delVrf_result other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSuccess()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("delVrf_result(");
+ boolean first = true;
+
+ sb.append("success:");
+ sb.append(this.success);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class delVrf_resultStandardSchemeFactory implements SchemeFactory {
+ public delVrf_resultStandardScheme getScheme() {
+ return new delVrf_resultStandardScheme();
+ }
+ }
+
+ private static class delVrf_resultStandardScheme extends StandardScheme<delVrf_result> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, delVrf_result struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 0: // SUCCESS
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, delVrf_result struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.isSetSuccess()) {
+ oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+ oprot.writeI32(struct.success);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class delVrf_resultTupleSchemeFactory implements SchemeFactory {
+ public delVrf_resultTupleScheme getScheme() {
+ return new delVrf_resultTupleScheme();
+ }
+ }
+
+ private static class delVrf_resultTupleScheme extends TupleScheme<delVrf_result> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, delVrf_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetSuccess()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetSuccess()) {
+ oprot.writeI32(struct.success);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, delVrf_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class pushRoute_args implements org.apache.thrift.TBase<pushRoute_args, pushRoute_args._Fields>, java.io.Serializable, Cloneable, Comparable<pushRoute_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("pushRoute_args");
+
+ private static final org.apache.thrift.protocol.TField PREFIX_FIELD_DESC = new org.apache.thrift.protocol.TField("prefix", org.apache.thrift.protocol.TType.STRING, (short)1);
+ private static final org.apache.thrift.protocol.TField NEXTHOP_FIELD_DESC = new org.apache.thrift.protocol.TField("nexthop", org.apache.thrift.protocol.TType.STRING, (short)2);
+ private static final org.apache.thrift.protocol.TField RD_FIELD_DESC = new org.apache.thrift.protocol.TField("rd", org.apache.thrift.protocol.TType.STRING, (short)3);
+ private static final org.apache.thrift.protocol.TField LABEL_FIELD_DESC = new org.apache.thrift.protocol.TField("label", org.apache.thrift.protocol.TType.I32, (short)4);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new pushRoute_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new pushRoute_argsTupleSchemeFactory());
+ }
+
+ public String prefix; // required
+ public String nexthop; // required
+ public String rd; // required
+ public int label; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ PREFIX((short)1, "prefix"),
+ NEXTHOP((short)2, "nexthop"),
+ RD((short)3, "rd"),
+ LABEL((short)4, "label");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // PREFIX
+ return PREFIX;
+ case 2: // NEXTHOP
+ return NEXTHOP;
+ case 3: // RD
+ return RD;
+ case 4: // LABEL
+ return LABEL;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __LABEL_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.PREFIX, new org.apache.thrift.meta_data.FieldMetaData("prefix", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ tmpMap.put(_Fields.NEXTHOP, new org.apache.thrift.meta_data.FieldMetaData("nexthop", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ tmpMap.put(_Fields.RD, new org.apache.thrift.meta_data.FieldMetaData("rd", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ tmpMap.put(_Fields.LABEL, new org.apache.thrift.meta_data.FieldMetaData("label", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(pushRoute_args.class, metaDataMap);
+ }
+
+ public pushRoute_args() {
+ }
+
+ public pushRoute_args(
+ String prefix,
+ String nexthop,
+ String rd,
+ int label)
+ {
+ this();
+ this.prefix = prefix;
+ this.nexthop = nexthop;
+ this.rd = rd;
+ this.label = label;
+ setLabelIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public pushRoute_args(pushRoute_args other) {
+ __isset_bitfield = other.__isset_bitfield;
+ if (other.isSetPrefix()) {
+ this.prefix = other.prefix;
+ }
+ if (other.isSetNexthop()) {
+ this.nexthop = other.nexthop;
+ }
+ if (other.isSetRd()) {
+ this.rd = other.rd;
+ }
+ this.label = other.label;
+ }
+
+ public pushRoute_args deepCopy() {
+ return new pushRoute_args(this);
+ }
+
+ @Override
+ public void clear() {
+ this.prefix = null;
+ this.nexthop = null;
+ this.rd = null;
+ setLabelIsSet(false);
+ this.label = 0;
+ }
+
+ public String getPrefix() {
+ return this.prefix;
+ }
+
+ public pushRoute_args setPrefix(String prefix) {
+ this.prefix = prefix;
+ return this;
+ }
+
+ public void unsetPrefix() {
+ this.prefix = null;
+ }
+
+ /** Returns true if field prefix is set (has been assigned a value) and false otherwise */
+ public boolean isSetPrefix() {
+ return this.prefix != null;
+ }
+
+ public void setPrefixIsSet(boolean value) {
+ if (!value) {
+ this.prefix = null;
+ }
+ }
+
+ public String getNexthop() {
+ return this.nexthop;
+ }
+
+ public pushRoute_args setNexthop(String nexthop) {
+ this.nexthop = nexthop;
+ return this;
+ }
+
+ public void unsetNexthop() {
+ this.nexthop = null;
+ }
+
+ /** Returns true if field nexthop is set (has been assigned a value) and false otherwise */
+ public boolean isSetNexthop() {
+ return this.nexthop != null;
+ }
+
+ public void setNexthopIsSet(boolean value) {
+ if (!value) {
+ this.nexthop = null;
+ }
+ }
+
+ public String getRd() {
+ return this.rd;
+ }
+
+ public pushRoute_args setRd(String rd) {
+ this.rd = rd;
+ return this;
+ }
+
+ public void unsetRd() {
+ this.rd = null;
+ }
+
+ /** Returns true if field rd is set (has been assigned a value) and false otherwise */
+ public boolean isSetRd() {
+ return this.rd != null;
+ }
+
+ public void setRdIsSet(boolean value) {
+ if (!value) {
+ this.rd = null;
+ }
+ }
+
+ public int getLabel() {
+ return this.label;
+ }
+
+ public pushRoute_args setLabel(int label) {
+ this.label = label;
+ setLabelIsSet(true);
+ return this;
+ }
+
+ public void unsetLabel() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __LABEL_ISSET_ID);
+ }
+
+ /** Returns true if field label is set (has been assigned a value) and false otherwise */
+ public boolean isSetLabel() {
+ return EncodingUtils.testBit(__isset_bitfield, __LABEL_ISSET_ID);
+ }
+
+ public void setLabelIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __LABEL_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case PREFIX:
+ if (value == null) {
+ unsetPrefix();
+ } else {
+ setPrefix((String)value);
+ }
+ break;
+
+ case NEXTHOP:
+ if (value == null) {
+ unsetNexthop();
+ } else {
+ setNexthop((String)value);
+ }
+ break;
+
+ case RD:
+ if (value == null) {
+ unsetRd();
+ } else {
+ setRd((String)value);
+ }
+ break;
+
+ case LABEL:
+ if (value == null) {
+ unsetLabel();
+ } else {
+ setLabel((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case PREFIX:
+ return getPrefix();
+
+ case NEXTHOP:
+ return getNexthop();
+
+ case RD:
+ return getRd();
+
+ case LABEL:
+ return Integer.valueOf(getLabel());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case PREFIX:
+ return isSetPrefix();
+ case NEXTHOP:
+ return isSetNexthop();
+ case RD:
+ return isSetRd();
+ case LABEL:
+ return isSetLabel();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof pushRoute_args)
+ return this.equals((pushRoute_args)that);
+ return false;
+ }
+
+ public boolean equals(pushRoute_args that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_prefix = true && this.isSetPrefix();
+ boolean that_present_prefix = true && that.isSetPrefix();
+ if (this_present_prefix || that_present_prefix) {
+ if (!(this_present_prefix && that_present_prefix))
+ return false;
+ if (!this.prefix.equals(that.prefix))
+ return false;
+ }
+
+ boolean this_present_nexthop = true && this.isSetNexthop();
+ boolean that_present_nexthop = true && that.isSetNexthop();
+ if (this_present_nexthop || that_present_nexthop) {
+ if (!(this_present_nexthop && that_present_nexthop))
+ return false;
+ if (!this.nexthop.equals(that.nexthop))
+ return false;
+ }
+
+ boolean this_present_rd = true && this.isSetRd();
+ boolean that_present_rd = true && that.isSetRd();
+ if (this_present_rd || that_present_rd) {
+ if (!(this_present_rd && that_present_rd))
+ return false;
+ if (!this.rd.equals(that.rd))
+ return false;
+ }
+
+ boolean this_present_label = true;
+ boolean that_present_label = true;
+ if (this_present_label || that_present_label) {
+ if (!(this_present_label && that_present_label))
+ return false;
+ if (this.label != that.label)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(pushRoute_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetPrefix()).compareTo(other.isSetPrefix());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetPrefix()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.prefix, other.prefix);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetNexthop()).compareTo(other.isSetNexthop());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetNexthop()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.nexthop, other.nexthop);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetRd()).compareTo(other.isSetRd());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetRd()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.rd, other.rd);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetLabel()).compareTo(other.isSetLabel());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetLabel()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.label, other.label);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("pushRoute_args(");
+ boolean first = true;
+
+ sb.append("prefix:");
+ if (this.prefix == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.prefix);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("nexthop:");
+ if (this.nexthop == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.nexthop);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("rd:");
+ if (this.rd == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.rd);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("label:");
+ sb.append(this.label);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class pushRoute_argsStandardSchemeFactory implements SchemeFactory {
+ public pushRoute_argsStandardScheme getScheme() {
+ return new pushRoute_argsStandardScheme();
+ }
+ }
+
+ private static class pushRoute_argsStandardScheme extends StandardScheme<pushRoute_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, pushRoute_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // PREFIX
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.prefix = iprot.readString();
+ struct.setPrefixIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 2: // NEXTHOP
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.nexthop = iprot.readString();
+ struct.setNexthopIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 3: // RD
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.rd = iprot.readString();
+ struct.setRdIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 4: // LABEL
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.label = iprot.readI32();
+ struct.setLabelIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, pushRoute_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.prefix != null) {
+ oprot.writeFieldBegin(PREFIX_FIELD_DESC);
+ oprot.writeString(struct.prefix);
+ oprot.writeFieldEnd();
+ }
+ if (struct.nexthop != null) {
+ oprot.writeFieldBegin(NEXTHOP_FIELD_DESC);
+ oprot.writeString(struct.nexthop);
+ oprot.writeFieldEnd();
+ }
+ if (struct.rd != null) {
+ oprot.writeFieldBegin(RD_FIELD_DESC);
+ oprot.writeString(struct.rd);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldBegin(LABEL_FIELD_DESC);
+ oprot.writeI32(struct.label);
+ oprot.writeFieldEnd();
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class pushRoute_argsTupleSchemeFactory implements SchemeFactory {
+ public pushRoute_argsTupleScheme getScheme() {
+ return new pushRoute_argsTupleScheme();
+ }
+ }
+
+ private static class pushRoute_argsTupleScheme extends TupleScheme<pushRoute_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, pushRoute_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetPrefix()) {
+ optionals.set(0);
+ }
+ if (struct.isSetNexthop()) {
+ optionals.set(1);
+ }
+ if (struct.isSetRd()) {
+ optionals.set(2);
+ }
+ if (struct.isSetLabel()) {
+ optionals.set(3);
+ }
+ oprot.writeBitSet(optionals, 4);
+ if (struct.isSetPrefix()) {
+ oprot.writeString(struct.prefix);
+ }
+ if (struct.isSetNexthop()) {
+ oprot.writeString(struct.nexthop);
+ }
+ if (struct.isSetRd()) {
+ oprot.writeString(struct.rd);
+ }
+ if (struct.isSetLabel()) {
+ oprot.writeI32(struct.label);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, pushRoute_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(4);
+ if (incoming.get(0)) {
+ struct.prefix = iprot.readString();
+ struct.setPrefixIsSet(true);
+ }
+ if (incoming.get(1)) {
+ struct.nexthop = iprot.readString();
+ struct.setNexthopIsSet(true);
+ }
+ if (incoming.get(2)) {
+ struct.rd = iprot.readString();
+ struct.setRdIsSet(true);
+ }
+ if (incoming.get(3)) {
+ struct.label = iprot.readI32();
+ struct.setLabelIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class pushRoute_result implements org.apache.thrift.TBase<pushRoute_result, pushRoute_result._Fields>, java.io.Serializable, Cloneable, Comparable<pushRoute_result> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("pushRoute_result");
+
+ private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new pushRoute_resultStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new pushRoute_resultTupleSchemeFactory());
+ }
+
+ public int success; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ SUCCESS((short)0, "success");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 0: // SUCCESS
+ return SUCCESS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __SUCCESS_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(pushRoute_result.class, metaDataMap);
+ }
+
+ public pushRoute_result() {
+ }
+
+ public pushRoute_result(
+ int success)
+ {
+ this();
+ this.success = success;
+ setSuccessIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public pushRoute_result(pushRoute_result other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.success = other.success;
+ }
+
+ public pushRoute_result deepCopy() {
+ return new pushRoute_result(this);
+ }
+
+ @Override
+ public void clear() {
+ setSuccessIsSet(false);
+ this.success = 0;
+ }
+
+ public int getSuccess() {
+ return this.success;
+ }
+
+ public pushRoute_result setSuccess(int success) {
+ this.success = success;
+ setSuccessIsSet(true);
+ return this;
+ }
+
+ public void unsetSuccess() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ /** Returns true if field success is set (has been assigned a value) and false otherwise */
+ public boolean isSetSuccess() {
+ return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ public void setSuccessIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case SUCCESS:
+ if (value == null) {
+ unsetSuccess();
+ } else {
+ setSuccess((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case SUCCESS:
+ return Integer.valueOf(getSuccess());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case SUCCESS:
+ return isSetSuccess();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof pushRoute_result)
+ return this.equals((pushRoute_result)that);
+ return false;
+ }
+
+ public boolean equals(pushRoute_result that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_success = true;
+ boolean that_present_success = true;
+ if (this_present_success || that_present_success) {
+ if (!(this_present_success && that_present_success))
+ return false;
+ if (this.success != that.success)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(pushRoute_result other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSuccess()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("pushRoute_result(");
+ boolean first = true;
+
+ sb.append("success:");
+ sb.append(this.success);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class pushRoute_resultStandardSchemeFactory implements SchemeFactory {
+ public pushRoute_resultStandardScheme getScheme() {
+ return new pushRoute_resultStandardScheme();
+ }
+ }
+
+ private static class pushRoute_resultStandardScheme extends StandardScheme<pushRoute_result> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, pushRoute_result struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 0: // SUCCESS
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, pushRoute_result struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.isSetSuccess()) {
+ oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+ oprot.writeI32(struct.success);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class pushRoute_resultTupleSchemeFactory implements SchemeFactory {
+ public pushRoute_resultTupleScheme getScheme() {
+ return new pushRoute_resultTupleScheme();
+ }
+ }
+
+ private static class pushRoute_resultTupleScheme extends TupleScheme<pushRoute_result> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, pushRoute_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetSuccess()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetSuccess()) {
+ oprot.writeI32(struct.success);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, pushRoute_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class withdrawRoute_args implements org.apache.thrift.TBase<withdrawRoute_args, withdrawRoute_args._Fields>, java.io.Serializable, Cloneable, Comparable<withdrawRoute_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("withdrawRoute_args");
+
+ private static final org.apache.thrift.protocol.TField PREFIX_FIELD_DESC = new org.apache.thrift.protocol.TField("prefix", org.apache.thrift.protocol.TType.STRING, (short)1);
+ private static final org.apache.thrift.protocol.TField RD_FIELD_DESC = new org.apache.thrift.protocol.TField("rd", org.apache.thrift.protocol.TType.STRING, (short)2);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new withdrawRoute_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new withdrawRoute_argsTupleSchemeFactory());
+ }
+
+ public String prefix; // required
+ public String rd; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ PREFIX((short)1, "prefix"),
+ RD((short)2, "rd");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // PREFIX
+ return PREFIX;
+ case 2: // RD
+ return RD;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.PREFIX, new org.apache.thrift.meta_data.FieldMetaData("prefix", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ tmpMap.put(_Fields.RD, new org.apache.thrift.meta_data.FieldMetaData("rd", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(withdrawRoute_args.class, metaDataMap);
+ }
+
+ public withdrawRoute_args() {
+ }
+
+ public withdrawRoute_args(
+ String prefix,
+ String rd)
+ {
+ this();
+ this.prefix = prefix;
+ this.rd = rd;
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public withdrawRoute_args(withdrawRoute_args other) {
+ if (other.isSetPrefix()) {
+ this.prefix = other.prefix;
+ }
+ if (other.isSetRd()) {
+ this.rd = other.rd;
+ }
+ }
+
+ public withdrawRoute_args deepCopy() {
+ return new withdrawRoute_args(this);
+ }
+
+ @Override
+ public void clear() {
+ this.prefix = null;
+ this.rd = null;
+ }
+
+ public String getPrefix() {
+ return this.prefix;
+ }
+
+ public withdrawRoute_args setPrefix(String prefix) {
+ this.prefix = prefix;
+ return this;
+ }
+
+ public void unsetPrefix() {
+ this.prefix = null;
+ }
+
+ /** Returns true if field prefix is set (has been assigned a value) and false otherwise */
+ public boolean isSetPrefix() {
+ return this.prefix != null;
+ }
+
+ public void setPrefixIsSet(boolean value) {
+ if (!value) {
+ this.prefix = null;
+ }
+ }
+
+ public String getRd() {
+ return this.rd;
+ }
+
+ public withdrawRoute_args setRd(String rd) {
+ this.rd = rd;
+ return this;
+ }
+
+ public void unsetRd() {
+ this.rd = null;
+ }
+
+ /** Returns true if field rd is set (has been assigned a value) and false otherwise */
+ public boolean isSetRd() {
+ return this.rd != null;
+ }
+
+ public void setRdIsSet(boolean value) {
+ if (!value) {
+ this.rd = null;
+ }
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case PREFIX:
+ if (value == null) {
+ unsetPrefix();
+ } else {
+ setPrefix((String)value);
+ }
+ break;
+
+ case RD:
+ if (value == null) {
+ unsetRd();
+ } else {
+ setRd((String)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case PREFIX:
+ return getPrefix();
+
+ case RD:
+ return getRd();
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case PREFIX:
+ return isSetPrefix();
+ case RD:
+ return isSetRd();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof withdrawRoute_args)
+ return this.equals((withdrawRoute_args)that);
+ return false;
+ }
+
+ public boolean equals(withdrawRoute_args that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_prefix = true && this.isSetPrefix();
+ boolean that_present_prefix = true && that.isSetPrefix();
+ if (this_present_prefix || that_present_prefix) {
+ if (!(this_present_prefix && that_present_prefix))
+ return false;
+ if (!this.prefix.equals(that.prefix))
+ return false;
+ }
+
+ boolean this_present_rd = true && this.isSetRd();
+ boolean that_present_rd = true && that.isSetRd();
+ if (this_present_rd || that_present_rd) {
+ if (!(this_present_rd && that_present_rd))
+ return false;
+ if (!this.rd.equals(that.rd))
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(withdrawRoute_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetPrefix()).compareTo(other.isSetPrefix());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetPrefix()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.prefix, other.prefix);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetRd()).compareTo(other.isSetRd());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetRd()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.rd, other.rd);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("withdrawRoute_args(");
+ boolean first = true;
+
+ sb.append("prefix:");
+ if (this.prefix == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.prefix);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("rd:");
+ if (this.rd == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.rd);
+ }
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class withdrawRoute_argsStandardSchemeFactory implements SchemeFactory {
+ public withdrawRoute_argsStandardScheme getScheme() {
+ return new withdrawRoute_argsStandardScheme();
+ }
+ }
+
+ private static class withdrawRoute_argsStandardScheme extends StandardScheme<withdrawRoute_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, withdrawRoute_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // PREFIX
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.prefix = iprot.readString();
+ struct.setPrefixIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 2: // RD
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.rd = iprot.readString();
+ struct.setRdIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, withdrawRoute_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.prefix != null) {
+ oprot.writeFieldBegin(PREFIX_FIELD_DESC);
+ oprot.writeString(struct.prefix);
+ oprot.writeFieldEnd();
+ }
+ if (struct.rd != null) {
+ oprot.writeFieldBegin(RD_FIELD_DESC);
+ oprot.writeString(struct.rd);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class withdrawRoute_argsTupleSchemeFactory implements SchemeFactory {
+ public withdrawRoute_argsTupleScheme getScheme() {
+ return new withdrawRoute_argsTupleScheme();
+ }
+ }
+
+ private static class withdrawRoute_argsTupleScheme extends TupleScheme<withdrawRoute_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, withdrawRoute_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetPrefix()) {
+ optionals.set(0);
+ }
+ if (struct.isSetRd()) {
+ optionals.set(1);
+ }
+ oprot.writeBitSet(optionals, 2);
+ if (struct.isSetPrefix()) {
+ oprot.writeString(struct.prefix);
+ }
+ if (struct.isSetRd()) {
+ oprot.writeString(struct.rd);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, withdrawRoute_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(2);
+ if (incoming.get(0)) {
+ struct.prefix = iprot.readString();
+ struct.setPrefixIsSet(true);
+ }
+ if (incoming.get(1)) {
+ struct.rd = iprot.readString();
+ struct.setRdIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class withdrawRoute_result implements org.apache.thrift.TBase<withdrawRoute_result, withdrawRoute_result._Fields>, java.io.Serializable, Cloneable, Comparable<withdrawRoute_result> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("withdrawRoute_result");
+
+ private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new withdrawRoute_resultStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new withdrawRoute_resultTupleSchemeFactory());
+ }
+
+ public int success; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ SUCCESS((short)0, "success");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 0: // SUCCESS
+ return SUCCESS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __SUCCESS_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(withdrawRoute_result.class, metaDataMap);
+ }
+
+ public withdrawRoute_result() {
+ }
+
+ public withdrawRoute_result(
+ int success)
+ {
+ this();
+ this.success = success;
+ setSuccessIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public withdrawRoute_result(withdrawRoute_result other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.success = other.success;
+ }
+
+ public withdrawRoute_result deepCopy() {
+ return new withdrawRoute_result(this);
+ }
+
+ @Override
+ public void clear() {
+ setSuccessIsSet(false);
+ this.success = 0;
+ }
+
+ public int getSuccess() {
+ return this.success;
+ }
+
+ public withdrawRoute_result setSuccess(int success) {
+ this.success = success;
+ setSuccessIsSet(true);
+ return this;
+ }
+
+ public void unsetSuccess() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ /** Returns true if field success is set (has been assigned a value) and false otherwise */
+ public boolean isSetSuccess() {
+ return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ public void setSuccessIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case SUCCESS:
+ if (value == null) {
+ unsetSuccess();
+ } else {
+ setSuccess((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case SUCCESS:
+ return Integer.valueOf(getSuccess());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case SUCCESS:
+ return isSetSuccess();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof withdrawRoute_result)
+ return this.equals((withdrawRoute_result)that);
+ return false;
+ }
+
+ public boolean equals(withdrawRoute_result that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_success = true;
+ boolean that_present_success = true;
+ if (this_present_success || that_present_success) {
+ if (!(this_present_success && that_present_success))
+ return false;
+ if (this.success != that.success)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(withdrawRoute_result other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSuccess()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("withdrawRoute_result(");
+ boolean first = true;
+
+ sb.append("success:");
+ sb.append(this.success);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class withdrawRoute_resultStandardSchemeFactory implements SchemeFactory {
+ public withdrawRoute_resultStandardScheme getScheme() {
+ return new withdrawRoute_resultStandardScheme();
+ }
+ }
+
+ private static class withdrawRoute_resultStandardScheme extends StandardScheme<withdrawRoute_result> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, withdrawRoute_result struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 0: // SUCCESS
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, withdrawRoute_result struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.isSetSuccess()) {
+ oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+ oprot.writeI32(struct.success);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class withdrawRoute_resultTupleSchemeFactory implements SchemeFactory {
+ public withdrawRoute_resultTupleScheme getScheme() {
+ return new withdrawRoute_resultTupleScheme();
+ }
+ }
+
+ private static class withdrawRoute_resultTupleScheme extends TupleScheme<withdrawRoute_result> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, withdrawRoute_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetSuccess()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetSuccess()) {
+ oprot.writeI32(struct.success);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, withdrawRoute_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class setEbgpMultihop_args implements org.apache.thrift.TBase<setEbgpMultihop_args, setEbgpMultihop_args._Fields>, java.io.Serializable, Cloneable, Comparable<setEbgpMultihop_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("setEbgpMultihop_args");
+
+ private static final org.apache.thrift.protocol.TField PEER_IP_FIELD_DESC = new org.apache.thrift.protocol.TField("peerIp", org.apache.thrift.protocol.TType.STRING, (short)1);
+ private static final org.apache.thrift.protocol.TField N_HOPS_FIELD_DESC = new org.apache.thrift.protocol.TField("nHops", org.apache.thrift.protocol.TType.I32, (short)2);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new setEbgpMultihop_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new setEbgpMultihop_argsTupleSchemeFactory());
+ }
+
+ public String peerIp; // required
+ public int nHops; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ PEER_IP((short)1, "peerIp"),
+ N_HOPS((short)2, "nHops");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // PEER_IP
+ return PEER_IP;
+ case 2: // N_HOPS
+ return N_HOPS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __NHOPS_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.PEER_IP, new org.apache.thrift.meta_data.FieldMetaData("peerIp", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ tmpMap.put(_Fields.N_HOPS, new org.apache.thrift.meta_data.FieldMetaData("nHops", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(setEbgpMultihop_args.class, metaDataMap);
+ }
+
+ public setEbgpMultihop_args() {
+ }
+
+ public setEbgpMultihop_args(
+ String peerIp,
+ int nHops)
+ {
+ this();
+ this.peerIp = peerIp;
+ this.nHops = nHops;
+ setNHopsIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public setEbgpMultihop_args(setEbgpMultihop_args other) {
+ __isset_bitfield = other.__isset_bitfield;
+ if (other.isSetPeerIp()) {
+ this.peerIp = other.peerIp;
+ }
+ this.nHops = other.nHops;
+ }
+
+ public setEbgpMultihop_args deepCopy() {
+ return new setEbgpMultihop_args(this);
+ }
+
+ @Override
+ public void clear() {
+ this.peerIp = null;
+ setNHopsIsSet(false);
+ this.nHops = 0;
+ }
+
+ public String getPeerIp() {
+ return this.peerIp;
+ }
+
+ public setEbgpMultihop_args setPeerIp(String peerIp) {
+ this.peerIp = peerIp;
+ return this;
+ }
+
+ public void unsetPeerIp() {
+ this.peerIp = null;
+ }
+
+ /** Returns true if field peerIp is set (has been assigned a value) and false otherwise */
+ public boolean isSetPeerIp() {
+ return this.peerIp != null;
+ }
+
+ public void setPeerIpIsSet(boolean value) {
+ if (!value) {
+ this.peerIp = null;
+ }
+ }
+
+ public int getNHops() {
+ return this.nHops;
+ }
+
+ public setEbgpMultihop_args setNHops(int nHops) {
+ this.nHops = nHops;
+ setNHopsIsSet(true);
+ return this;
+ }
+
+ public void unsetNHops() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __NHOPS_ISSET_ID);
+ }
+
+ /** Returns true if field nHops is set (has been assigned a value) and false otherwise */
+ public boolean isSetNHops() {
+ return EncodingUtils.testBit(__isset_bitfield, __NHOPS_ISSET_ID);
+ }
+
+ public void setNHopsIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __NHOPS_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case PEER_IP:
+ if (value == null) {
+ unsetPeerIp();
+ } else {
+ setPeerIp((String)value);
+ }
+ break;
+
+ case N_HOPS:
+ if (value == null) {
+ unsetNHops();
+ } else {
+ setNHops((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case PEER_IP:
+ return getPeerIp();
+
+ case N_HOPS:
+ return Integer.valueOf(getNHops());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case PEER_IP:
+ return isSetPeerIp();
+ case N_HOPS:
+ return isSetNHops();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof setEbgpMultihop_args)
+ return this.equals((setEbgpMultihop_args)that);
+ return false;
+ }
+
+ public boolean equals(setEbgpMultihop_args that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_peerIp = true && this.isSetPeerIp();
+ boolean that_present_peerIp = true && that.isSetPeerIp();
+ if (this_present_peerIp || that_present_peerIp) {
+ if (!(this_present_peerIp && that_present_peerIp))
+ return false;
+ if (!this.peerIp.equals(that.peerIp))
+ return false;
+ }
+
+ boolean this_present_nHops = true;
+ boolean that_present_nHops = true;
+ if (this_present_nHops || that_present_nHops) {
+ if (!(this_present_nHops && that_present_nHops))
+ return false;
+ if (this.nHops != that.nHops)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(setEbgpMultihop_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetPeerIp()).compareTo(other.isSetPeerIp());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetPeerIp()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.peerIp, other.peerIp);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetNHops()).compareTo(other.isSetNHops());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetNHops()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.nHops, other.nHops);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("setEbgpMultihop_args(");
+ boolean first = true;
+
+ sb.append("peerIp:");
+ if (this.peerIp == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.peerIp);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("nHops:");
+ sb.append(this.nHops);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class setEbgpMultihop_argsStandardSchemeFactory implements SchemeFactory {
+ public setEbgpMultihop_argsStandardScheme getScheme() {
+ return new setEbgpMultihop_argsStandardScheme();
+ }
+ }
+
+ private static class setEbgpMultihop_argsStandardScheme extends StandardScheme<setEbgpMultihop_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, setEbgpMultihop_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // PEER_IP
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.peerIp = iprot.readString();
+ struct.setPeerIpIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 2: // N_HOPS
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.nHops = iprot.readI32();
+ struct.setNHopsIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, setEbgpMultihop_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.peerIp != null) {
+ oprot.writeFieldBegin(PEER_IP_FIELD_DESC);
+ oprot.writeString(struct.peerIp);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldBegin(N_HOPS_FIELD_DESC);
+ oprot.writeI32(struct.nHops);
+ oprot.writeFieldEnd();
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class setEbgpMultihop_argsTupleSchemeFactory implements SchemeFactory {
+ public setEbgpMultihop_argsTupleScheme getScheme() {
+ return new setEbgpMultihop_argsTupleScheme();
+ }
+ }
+
+ private static class setEbgpMultihop_argsTupleScheme extends TupleScheme<setEbgpMultihop_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, setEbgpMultihop_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetPeerIp()) {
+ optionals.set(0);
+ }
+ if (struct.isSetNHops()) {
+ optionals.set(1);
+ }
+ oprot.writeBitSet(optionals, 2);
+ if (struct.isSetPeerIp()) {
+ oprot.writeString(struct.peerIp);
+ }
+ if (struct.isSetNHops()) {
+ oprot.writeI32(struct.nHops);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, setEbgpMultihop_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(2);
+ if (incoming.get(0)) {
+ struct.peerIp = iprot.readString();
+ struct.setPeerIpIsSet(true);
+ }
+ if (incoming.get(1)) {
+ struct.nHops = iprot.readI32();
+ struct.setNHopsIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class setEbgpMultihop_result implements org.apache.thrift.TBase<setEbgpMultihop_result, setEbgpMultihop_result._Fields>, java.io.Serializable, Cloneable, Comparable<setEbgpMultihop_result> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("setEbgpMultihop_result");
+
+ private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new setEbgpMultihop_resultStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new setEbgpMultihop_resultTupleSchemeFactory());
+ }
+
+ public int success; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ SUCCESS((short)0, "success");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 0: // SUCCESS
+ return SUCCESS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __SUCCESS_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(setEbgpMultihop_result.class, metaDataMap);
+ }
+
+ public setEbgpMultihop_result() {
+ }
+
+ public setEbgpMultihop_result(
+ int success)
+ {
+ this();
+ this.success = success;
+ setSuccessIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public setEbgpMultihop_result(setEbgpMultihop_result other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.success = other.success;
+ }
+
+ public setEbgpMultihop_result deepCopy() {
+ return new setEbgpMultihop_result(this);
+ }
+
+ @Override
+ public void clear() {
+ setSuccessIsSet(false);
+ this.success = 0;
+ }
+
+ public int getSuccess() {
+ return this.success;
+ }
+
+ public setEbgpMultihop_result setSuccess(int success) {
+ this.success = success;
+ setSuccessIsSet(true);
+ return this;
+ }
+
+ public void unsetSuccess() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ /** Returns true if field success is set (has been assigned a value) and false otherwise */
+ public boolean isSetSuccess() {
+ return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ public void setSuccessIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case SUCCESS:
+ if (value == null) {
+ unsetSuccess();
+ } else {
+ setSuccess((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case SUCCESS:
+ return Integer.valueOf(getSuccess());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case SUCCESS:
+ return isSetSuccess();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof setEbgpMultihop_result)
+ return this.equals((setEbgpMultihop_result)that);
+ return false;
+ }
+
+ public boolean equals(setEbgpMultihop_result that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_success = true;
+ boolean that_present_success = true;
+ if (this_present_success || that_present_success) {
+ if (!(this_present_success && that_present_success))
+ return false;
+ if (this.success != that.success)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(setEbgpMultihop_result other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSuccess()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("setEbgpMultihop_result(");
+ boolean first = true;
+
+ sb.append("success:");
+ sb.append(this.success);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class setEbgpMultihop_resultStandardSchemeFactory implements SchemeFactory {
+ public setEbgpMultihop_resultStandardScheme getScheme() {
+ return new setEbgpMultihop_resultStandardScheme();
+ }
+ }
+
+ private static class setEbgpMultihop_resultStandardScheme extends StandardScheme<setEbgpMultihop_result> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, setEbgpMultihop_result struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 0: // SUCCESS
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, setEbgpMultihop_result struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.isSetSuccess()) {
+ oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+ oprot.writeI32(struct.success);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class setEbgpMultihop_resultTupleSchemeFactory implements SchemeFactory {
+ public setEbgpMultihop_resultTupleScheme getScheme() {
+ return new setEbgpMultihop_resultTupleScheme();
+ }
+ }
+
+ private static class setEbgpMultihop_resultTupleScheme extends TupleScheme<setEbgpMultihop_result> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, setEbgpMultihop_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetSuccess()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetSuccess()) {
+ oprot.writeI32(struct.success);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, setEbgpMultihop_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class unsetEbgpMultihop_args implements org.apache.thrift.TBase<unsetEbgpMultihop_args, unsetEbgpMultihop_args._Fields>, java.io.Serializable, Cloneable, Comparable<unsetEbgpMultihop_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("unsetEbgpMultihop_args");
+
+ private static final org.apache.thrift.protocol.TField PEER_IP_FIELD_DESC = new org.apache.thrift.protocol.TField("peerIp", org.apache.thrift.protocol.TType.STRING, (short)1);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new unsetEbgpMultihop_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new unsetEbgpMultihop_argsTupleSchemeFactory());
+ }
+
+ public String peerIp; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ PEER_IP((short)1, "peerIp");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // PEER_IP
+ return PEER_IP;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.PEER_IP, new org.apache.thrift.meta_data.FieldMetaData("peerIp", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(unsetEbgpMultihop_args.class, metaDataMap);
+ }
+
+ public unsetEbgpMultihop_args() {
+ }
+
+ public unsetEbgpMultihop_args(
+ String peerIp)
+ {
+ this();
+ this.peerIp = peerIp;
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public unsetEbgpMultihop_args(unsetEbgpMultihop_args other) {
+ if (other.isSetPeerIp()) {
+ this.peerIp = other.peerIp;
+ }
+ }
+
+ public unsetEbgpMultihop_args deepCopy() {
+ return new unsetEbgpMultihop_args(this);
+ }
+
+ @Override
+ public void clear() {
+ this.peerIp = null;
+ }
+
+ public String getPeerIp() {
+ return this.peerIp;
+ }
+
+ public unsetEbgpMultihop_args setPeerIp(String peerIp) {
+ this.peerIp = peerIp;
+ return this;
+ }
+
+ public void unsetPeerIp() {
+ this.peerIp = null;
+ }
+
+ /** Returns true if field peerIp is set (has been assigned a value) and false otherwise */
+ public boolean isSetPeerIp() {
+ return this.peerIp != null;
+ }
+
+ public void setPeerIpIsSet(boolean value) {
+ if (!value) {
+ this.peerIp = null;
+ }
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case PEER_IP:
+ if (value == null) {
+ unsetPeerIp();
+ } else {
+ setPeerIp((String)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case PEER_IP:
+ return getPeerIp();
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case PEER_IP:
+ return isSetPeerIp();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof unsetEbgpMultihop_args)
+ return this.equals((unsetEbgpMultihop_args)that);
+ return false;
+ }
+
+ public boolean equals(unsetEbgpMultihop_args that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_peerIp = true && this.isSetPeerIp();
+ boolean that_present_peerIp = true && that.isSetPeerIp();
+ if (this_present_peerIp || that_present_peerIp) {
+ if (!(this_present_peerIp && that_present_peerIp))
+ return false;
+ if (!this.peerIp.equals(that.peerIp))
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(unsetEbgpMultihop_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetPeerIp()).compareTo(other.isSetPeerIp());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetPeerIp()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.peerIp, other.peerIp);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("unsetEbgpMultihop_args(");
+ boolean first = true;
+
+ sb.append("peerIp:");
+ if (this.peerIp == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.peerIp);
+ }
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class unsetEbgpMultihop_argsStandardSchemeFactory implements SchemeFactory {
+ public unsetEbgpMultihop_argsStandardScheme getScheme() {
+ return new unsetEbgpMultihop_argsStandardScheme();
+ }
+ }
+
+ private static class unsetEbgpMultihop_argsStandardScheme extends StandardScheme<unsetEbgpMultihop_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, unsetEbgpMultihop_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // PEER_IP
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.peerIp = iprot.readString();
+ struct.setPeerIpIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, unsetEbgpMultihop_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.peerIp != null) {
+ oprot.writeFieldBegin(PEER_IP_FIELD_DESC);
+ oprot.writeString(struct.peerIp);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class unsetEbgpMultihop_argsTupleSchemeFactory implements SchemeFactory {
+ public unsetEbgpMultihop_argsTupleScheme getScheme() {
+ return new unsetEbgpMultihop_argsTupleScheme();
+ }
+ }
+
+ private static class unsetEbgpMultihop_argsTupleScheme extends TupleScheme<unsetEbgpMultihop_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, unsetEbgpMultihop_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetPeerIp()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetPeerIp()) {
+ oprot.writeString(struct.peerIp);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, unsetEbgpMultihop_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.peerIp = iprot.readString();
+ struct.setPeerIpIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class unsetEbgpMultihop_result implements org.apache.thrift.TBase<unsetEbgpMultihop_result, unsetEbgpMultihop_result._Fields>, java.io.Serializable, Cloneable, Comparable<unsetEbgpMultihop_result> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("unsetEbgpMultihop_result");
+
+ private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new unsetEbgpMultihop_resultStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new unsetEbgpMultihop_resultTupleSchemeFactory());
+ }
+
+ public int success; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ SUCCESS((short)0, "success");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 0: // SUCCESS
+ return SUCCESS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __SUCCESS_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(unsetEbgpMultihop_result.class, metaDataMap);
+ }
+
+ public unsetEbgpMultihop_result() {
+ }
+
+ public unsetEbgpMultihop_result(
+ int success)
+ {
+ this();
+ this.success = success;
+ setSuccessIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public unsetEbgpMultihop_result(unsetEbgpMultihop_result other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.success = other.success;
+ }
+
+ public unsetEbgpMultihop_result deepCopy() {
+ return new unsetEbgpMultihop_result(this);
+ }
+
+ @Override
+ public void clear() {
+ setSuccessIsSet(false);
+ this.success = 0;
+ }
+
+ public int getSuccess() {
+ return this.success;
+ }
+
+ public unsetEbgpMultihop_result setSuccess(int success) {
+ this.success = success;
+ setSuccessIsSet(true);
+ return this;
+ }
+
+ public void unsetSuccess() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ /** Returns true if field success is set (has been assigned a value) and false otherwise */
+ public boolean isSetSuccess() {
+ return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ public void setSuccessIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case SUCCESS:
+ if (value == null) {
+ unsetSuccess();
+ } else {
+ setSuccess((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case SUCCESS:
+ return Integer.valueOf(getSuccess());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case SUCCESS:
+ return isSetSuccess();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof unsetEbgpMultihop_result)
+ return this.equals((unsetEbgpMultihop_result)that);
+ return false;
+ }
+
+ public boolean equals(unsetEbgpMultihop_result that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_success = true;
+ boolean that_present_success = true;
+ if (this_present_success || that_present_success) {
+ if (!(this_present_success && that_present_success))
+ return false;
+ if (this.success != that.success)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(unsetEbgpMultihop_result other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSuccess()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("unsetEbgpMultihop_result(");
+ boolean first = true;
+
+ sb.append("success:");
+ sb.append(this.success);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class unsetEbgpMultihop_resultStandardSchemeFactory implements SchemeFactory {
+ public unsetEbgpMultihop_resultStandardScheme getScheme() {
+ return new unsetEbgpMultihop_resultStandardScheme();
+ }
+ }
+
+ private static class unsetEbgpMultihop_resultStandardScheme extends StandardScheme<unsetEbgpMultihop_result> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, unsetEbgpMultihop_result struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 0: // SUCCESS
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, unsetEbgpMultihop_result struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.isSetSuccess()) {
+ oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+ oprot.writeI32(struct.success);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class unsetEbgpMultihop_resultTupleSchemeFactory implements SchemeFactory {
+ public unsetEbgpMultihop_resultTupleScheme getScheme() {
+ return new unsetEbgpMultihop_resultTupleScheme();
+ }
+ }
+
+ private static class unsetEbgpMultihop_resultTupleScheme extends TupleScheme<unsetEbgpMultihop_result> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, unsetEbgpMultihop_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetSuccess()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetSuccess()) {
+ oprot.writeI32(struct.success);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, unsetEbgpMultihop_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class setUpdateSource_args implements org.apache.thrift.TBase<setUpdateSource_args, setUpdateSource_args._Fields>, java.io.Serializable, Cloneable, Comparable<setUpdateSource_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("setUpdateSource_args");
+
+ private static final org.apache.thrift.protocol.TField PEER_IP_FIELD_DESC = new org.apache.thrift.protocol.TField("peerIp", org.apache.thrift.protocol.TType.STRING, (short)1);
+ private static final org.apache.thrift.protocol.TField SRC_IP_FIELD_DESC = new org.apache.thrift.protocol.TField("srcIp", org.apache.thrift.protocol.TType.STRING, (short)2);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new setUpdateSource_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new setUpdateSource_argsTupleSchemeFactory());
+ }
+
+ public String peerIp; // required
+ public String srcIp; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ PEER_IP((short)1, "peerIp"),
+ SRC_IP((short)2, "srcIp");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // PEER_IP
+ return PEER_IP;
+ case 2: // SRC_IP
+ return SRC_IP;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.PEER_IP, new org.apache.thrift.meta_data.FieldMetaData("peerIp", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ tmpMap.put(_Fields.SRC_IP, new org.apache.thrift.meta_data.FieldMetaData("srcIp", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(setUpdateSource_args.class, metaDataMap);
+ }
+
+ public setUpdateSource_args() {
+ }
+
+ public setUpdateSource_args(
+ String peerIp,
+ String srcIp)
+ {
+ this();
+ this.peerIp = peerIp;
+ this.srcIp = srcIp;
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public setUpdateSource_args(setUpdateSource_args other) {
+ if (other.isSetPeerIp()) {
+ this.peerIp = other.peerIp;
+ }
+ if (other.isSetSrcIp()) {
+ this.srcIp = other.srcIp;
+ }
+ }
+
+ public setUpdateSource_args deepCopy() {
+ return new setUpdateSource_args(this);
+ }
+
+ @Override
+ public void clear() {
+ this.peerIp = null;
+ this.srcIp = null;
+ }
+
+ public String getPeerIp() {
+ return this.peerIp;
+ }
+
+ public setUpdateSource_args setPeerIp(String peerIp) {
+ this.peerIp = peerIp;
+ return this;
+ }
+
+ public void unsetPeerIp() {
+ this.peerIp = null;
+ }
+
+ /** Returns true if field peerIp is set (has been assigned a value) and false otherwise */
+ public boolean isSetPeerIp() {
+ return this.peerIp != null;
+ }
+
+ public void setPeerIpIsSet(boolean value) {
+ if (!value) {
+ this.peerIp = null;
+ }
+ }
+
+ public String getSrcIp() {
+ return this.srcIp;
+ }
+
+ public setUpdateSource_args setSrcIp(String srcIp) {
+ this.srcIp = srcIp;
+ return this;
+ }
+
+ public void unsetSrcIp() {
+ this.srcIp = null;
+ }
+
+ /** Returns true if field srcIp is set (has been assigned a value) and false otherwise */
+ public boolean isSetSrcIp() {
+ return this.srcIp != null;
+ }
+
+ public void setSrcIpIsSet(boolean value) {
+ if (!value) {
+ this.srcIp = null;
+ }
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case PEER_IP:
+ if (value == null) {
+ unsetPeerIp();
+ } else {
+ setPeerIp((String)value);
+ }
+ break;
+
+ case SRC_IP:
+ if (value == null) {
+ unsetSrcIp();
+ } else {
+ setSrcIp((String)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case PEER_IP:
+ return getPeerIp();
+
+ case SRC_IP:
+ return getSrcIp();
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case PEER_IP:
+ return isSetPeerIp();
+ case SRC_IP:
+ return isSetSrcIp();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof setUpdateSource_args)
+ return this.equals((setUpdateSource_args)that);
+ return false;
+ }
+
+ public boolean equals(setUpdateSource_args that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_peerIp = true && this.isSetPeerIp();
+ boolean that_present_peerIp = true && that.isSetPeerIp();
+ if (this_present_peerIp || that_present_peerIp) {
+ if (!(this_present_peerIp && that_present_peerIp))
+ return false;
+ if (!this.peerIp.equals(that.peerIp))
+ return false;
+ }
+
+ boolean this_present_srcIp = true && this.isSetSrcIp();
+ boolean that_present_srcIp = true && that.isSetSrcIp();
+ if (this_present_srcIp || that_present_srcIp) {
+ if (!(this_present_srcIp && that_present_srcIp))
+ return false;
+ if (!this.srcIp.equals(that.srcIp))
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(setUpdateSource_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetPeerIp()).compareTo(other.isSetPeerIp());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetPeerIp()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.peerIp, other.peerIp);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetSrcIp()).compareTo(other.isSetSrcIp());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSrcIp()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.srcIp, other.srcIp);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("setUpdateSource_args(");
+ boolean first = true;
+
+ sb.append("peerIp:");
+ if (this.peerIp == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.peerIp);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("srcIp:");
+ if (this.srcIp == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.srcIp);
+ }
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class setUpdateSource_argsStandardSchemeFactory implements SchemeFactory {
+ public setUpdateSource_argsStandardScheme getScheme() {
+ return new setUpdateSource_argsStandardScheme();
+ }
+ }
+
+ private static class setUpdateSource_argsStandardScheme extends StandardScheme<setUpdateSource_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, setUpdateSource_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // PEER_IP
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.peerIp = iprot.readString();
+ struct.setPeerIpIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 2: // SRC_IP
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.srcIp = iprot.readString();
+ struct.setSrcIpIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, setUpdateSource_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.peerIp != null) {
+ oprot.writeFieldBegin(PEER_IP_FIELD_DESC);
+ oprot.writeString(struct.peerIp);
+ oprot.writeFieldEnd();
+ }
+ if (struct.srcIp != null) {
+ oprot.writeFieldBegin(SRC_IP_FIELD_DESC);
+ oprot.writeString(struct.srcIp);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class setUpdateSource_argsTupleSchemeFactory implements SchemeFactory {
+ public setUpdateSource_argsTupleScheme getScheme() {
+ return new setUpdateSource_argsTupleScheme();
+ }
+ }
+
+ private static class setUpdateSource_argsTupleScheme extends TupleScheme<setUpdateSource_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, setUpdateSource_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetPeerIp()) {
+ optionals.set(0);
+ }
+ if (struct.isSetSrcIp()) {
+ optionals.set(1);
+ }
+ oprot.writeBitSet(optionals, 2);
+ if (struct.isSetPeerIp()) {
+ oprot.writeString(struct.peerIp);
+ }
+ if (struct.isSetSrcIp()) {
+ oprot.writeString(struct.srcIp);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, setUpdateSource_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(2);
+ if (incoming.get(0)) {
+ struct.peerIp = iprot.readString();
+ struct.setPeerIpIsSet(true);
+ }
+ if (incoming.get(1)) {
+ struct.srcIp = iprot.readString();
+ struct.setSrcIpIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class setUpdateSource_result implements org.apache.thrift.TBase<setUpdateSource_result, setUpdateSource_result._Fields>, java.io.Serializable, Cloneable, Comparable<setUpdateSource_result> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("setUpdateSource_result");
+
+ private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new setUpdateSource_resultStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new setUpdateSource_resultTupleSchemeFactory());
+ }
+
+ public int success; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ SUCCESS((short)0, "success");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 0: // SUCCESS
+ return SUCCESS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __SUCCESS_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(setUpdateSource_result.class, metaDataMap);
+ }
+
+ public setUpdateSource_result() {
+ }
+
+ public setUpdateSource_result(
+ int success)
+ {
+ this();
+ this.success = success;
+ setSuccessIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public setUpdateSource_result(setUpdateSource_result other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.success = other.success;
+ }
+
+ public setUpdateSource_result deepCopy() {
+ return new setUpdateSource_result(this);
+ }
+
+ @Override
+ public void clear() {
+ setSuccessIsSet(false);
+ this.success = 0;
+ }
+
+ public int getSuccess() {
+ return this.success;
+ }
+
+ public setUpdateSource_result setSuccess(int success) {
+ this.success = success;
+ setSuccessIsSet(true);
+ return this;
+ }
+
+ public void unsetSuccess() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ /** Returns true if field success is set (has been assigned a value) and false otherwise */
+ public boolean isSetSuccess() {
+ return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ public void setSuccessIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case SUCCESS:
+ if (value == null) {
+ unsetSuccess();
+ } else {
+ setSuccess((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case SUCCESS:
+ return Integer.valueOf(getSuccess());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case SUCCESS:
+ return isSetSuccess();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof setUpdateSource_result)
+ return this.equals((setUpdateSource_result)that);
+ return false;
+ }
+
+ public boolean equals(setUpdateSource_result that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_success = true;
+ boolean that_present_success = true;
+ if (this_present_success || that_present_success) {
+ if (!(this_present_success && that_present_success))
+ return false;
+ if (this.success != that.success)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(setUpdateSource_result other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSuccess()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("setUpdateSource_result(");
+ boolean first = true;
+
+ sb.append("success:");
+ sb.append(this.success);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class setUpdateSource_resultStandardSchemeFactory implements SchemeFactory {
+ public setUpdateSource_resultStandardScheme getScheme() {
+ return new setUpdateSource_resultStandardScheme();
+ }
+ }
+
+ private static class setUpdateSource_resultStandardScheme extends StandardScheme<setUpdateSource_result> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, setUpdateSource_result struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 0: // SUCCESS
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, setUpdateSource_result struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.isSetSuccess()) {
+ oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+ oprot.writeI32(struct.success);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class setUpdateSource_resultTupleSchemeFactory implements SchemeFactory {
+ public setUpdateSource_resultTupleScheme getScheme() {
+ return new setUpdateSource_resultTupleScheme();
+ }
+ }
+
+ private static class setUpdateSource_resultTupleScheme extends TupleScheme<setUpdateSource_result> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, setUpdateSource_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetSuccess()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetSuccess()) {
+ oprot.writeI32(struct.success);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, setUpdateSource_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class unsetUpdateSource_args implements org.apache.thrift.TBase<unsetUpdateSource_args, unsetUpdateSource_args._Fields>, java.io.Serializable, Cloneable, Comparable<unsetUpdateSource_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("unsetUpdateSource_args");
+
+ private static final org.apache.thrift.protocol.TField PEER_IP_FIELD_DESC = new org.apache.thrift.protocol.TField("peerIp", org.apache.thrift.protocol.TType.STRING, (short)1);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new unsetUpdateSource_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new unsetUpdateSource_argsTupleSchemeFactory());
+ }
+
+ public String peerIp; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ PEER_IP((short)1, "peerIp");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // PEER_IP
+ return PEER_IP;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.PEER_IP, new org.apache.thrift.meta_data.FieldMetaData("peerIp", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(unsetUpdateSource_args.class, metaDataMap);
+ }
+
+ public unsetUpdateSource_args() {
+ }
+
+ public unsetUpdateSource_args(
+ String peerIp)
+ {
+ this();
+ this.peerIp = peerIp;
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public unsetUpdateSource_args(unsetUpdateSource_args other) {
+ if (other.isSetPeerIp()) {
+ this.peerIp = other.peerIp;
+ }
+ }
+
+ public unsetUpdateSource_args deepCopy() {
+ return new unsetUpdateSource_args(this);
+ }
+
+ @Override
+ public void clear() {
+ this.peerIp = null;
+ }
+
+ public String getPeerIp() {
+ return this.peerIp;
+ }
+
+ public unsetUpdateSource_args setPeerIp(String peerIp) {
+ this.peerIp = peerIp;
+ return this;
+ }
+
+ public void unsetPeerIp() {
+ this.peerIp = null;
+ }
+
+ /** Returns true if field peerIp is set (has been assigned a value) and false otherwise */
+ public boolean isSetPeerIp() {
+ return this.peerIp != null;
+ }
+
+ public void setPeerIpIsSet(boolean value) {
+ if (!value) {
+ this.peerIp = null;
+ }
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case PEER_IP:
+ if (value == null) {
+ unsetPeerIp();
+ } else {
+ setPeerIp((String)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case PEER_IP:
+ return getPeerIp();
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case PEER_IP:
+ return isSetPeerIp();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof unsetUpdateSource_args)
+ return this.equals((unsetUpdateSource_args)that);
+ return false;
+ }
+
+ public boolean equals(unsetUpdateSource_args that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_peerIp = true && this.isSetPeerIp();
+ boolean that_present_peerIp = true && that.isSetPeerIp();
+ if (this_present_peerIp || that_present_peerIp) {
+ if (!(this_present_peerIp && that_present_peerIp))
+ return false;
+ if (!this.peerIp.equals(that.peerIp))
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(unsetUpdateSource_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetPeerIp()).compareTo(other.isSetPeerIp());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetPeerIp()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.peerIp, other.peerIp);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("unsetUpdateSource_args(");
+ boolean first = true;
+
+ sb.append("peerIp:");
+ if (this.peerIp == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.peerIp);
+ }
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class unsetUpdateSource_argsStandardSchemeFactory implements SchemeFactory {
+ public unsetUpdateSource_argsStandardScheme getScheme() {
+ return new unsetUpdateSource_argsStandardScheme();
+ }
+ }
+
+ private static class unsetUpdateSource_argsStandardScheme extends StandardScheme<unsetUpdateSource_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, unsetUpdateSource_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // PEER_IP
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.peerIp = iprot.readString();
+ struct.setPeerIpIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, unsetUpdateSource_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.peerIp != null) {
+ oprot.writeFieldBegin(PEER_IP_FIELD_DESC);
+ oprot.writeString(struct.peerIp);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class unsetUpdateSource_argsTupleSchemeFactory implements SchemeFactory {
+ public unsetUpdateSource_argsTupleScheme getScheme() {
+ return new unsetUpdateSource_argsTupleScheme();
+ }
+ }
+
+ private static class unsetUpdateSource_argsTupleScheme extends TupleScheme<unsetUpdateSource_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, unsetUpdateSource_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetPeerIp()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetPeerIp()) {
+ oprot.writeString(struct.peerIp);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, unsetUpdateSource_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.peerIp = iprot.readString();
+ struct.setPeerIpIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class unsetUpdateSource_result implements org.apache.thrift.TBase<unsetUpdateSource_result, unsetUpdateSource_result._Fields>, java.io.Serializable, Cloneable, Comparable<unsetUpdateSource_result> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("unsetUpdateSource_result");
+
+ private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new unsetUpdateSource_resultStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new unsetUpdateSource_resultTupleSchemeFactory());
+ }
+
+ public int success; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ SUCCESS((short)0, "success");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 0: // SUCCESS
+ return SUCCESS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __SUCCESS_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(unsetUpdateSource_result.class, metaDataMap);
+ }
+
+ public unsetUpdateSource_result() {
+ }
+
+ public unsetUpdateSource_result(
+ int success)
+ {
+ this();
+ this.success = success;
+ setSuccessIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public unsetUpdateSource_result(unsetUpdateSource_result other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.success = other.success;
+ }
+
+ public unsetUpdateSource_result deepCopy() {
+ return new unsetUpdateSource_result(this);
+ }
+
+ @Override
+ public void clear() {
+ setSuccessIsSet(false);
+ this.success = 0;
+ }
+
+ public int getSuccess() {
+ return this.success;
+ }
+
+ public unsetUpdateSource_result setSuccess(int success) {
+ this.success = success;
+ setSuccessIsSet(true);
+ return this;
+ }
+
+ public void unsetSuccess() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ /** Returns true if field success is set (has been assigned a value) and false otherwise */
+ public boolean isSetSuccess() {
+ return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ public void setSuccessIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case SUCCESS:
+ if (value == null) {
+ unsetSuccess();
+ } else {
+ setSuccess((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case SUCCESS:
+ return Integer.valueOf(getSuccess());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case SUCCESS:
+ return isSetSuccess();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof unsetUpdateSource_result)
+ return this.equals((unsetUpdateSource_result)that);
+ return false;
+ }
+
+ public boolean equals(unsetUpdateSource_result that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_success = true;
+ boolean that_present_success = true;
+ if (this_present_success || that_present_success) {
+ if (!(this_present_success && that_present_success))
+ return false;
+ if (this.success != that.success)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(unsetUpdateSource_result other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSuccess()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("unsetUpdateSource_result(");
+ boolean first = true;
+
+ sb.append("success:");
+ sb.append(this.success);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class unsetUpdateSource_resultStandardSchemeFactory implements SchemeFactory {
+ public unsetUpdateSource_resultStandardScheme getScheme() {
+ return new unsetUpdateSource_resultStandardScheme();
+ }
+ }
+
+ private static class unsetUpdateSource_resultStandardScheme extends StandardScheme<unsetUpdateSource_result> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, unsetUpdateSource_result struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 0: // SUCCESS
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, unsetUpdateSource_result struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.isSetSuccess()) {
+ oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+ oprot.writeI32(struct.success);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class unsetUpdateSource_resultTupleSchemeFactory implements SchemeFactory {
+ public unsetUpdateSource_resultTupleScheme getScheme() {
+ return new unsetUpdateSource_resultTupleScheme();
+ }
+ }
+
+ private static class unsetUpdateSource_resultTupleScheme extends TupleScheme<unsetUpdateSource_result> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, unsetUpdateSource_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetSuccess()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetSuccess()) {
+ oprot.writeI32(struct.success);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, unsetUpdateSource_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class enableAddressFamily_args implements org.apache.thrift.TBase<enableAddressFamily_args, enableAddressFamily_args._Fields>, java.io.Serializable, Cloneable, Comparable<enableAddressFamily_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("enableAddressFamily_args");
+
+ private static final org.apache.thrift.protocol.TField PEER_IP_FIELD_DESC = new org.apache.thrift.protocol.TField("peerIp", org.apache.thrift.protocol.TType.STRING, (short)1);
+ private static final org.apache.thrift.protocol.TField AFI_FIELD_DESC = new org.apache.thrift.protocol.TField("afi", org.apache.thrift.protocol.TType.I32, (short)2);
+ private static final org.apache.thrift.protocol.TField SAFI_FIELD_DESC = new org.apache.thrift.protocol.TField("safi", org.apache.thrift.protocol.TType.I32, (short)3);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new enableAddressFamily_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new enableAddressFamily_argsTupleSchemeFactory());
+ }
+
+ public String peerIp; // required
+ /**
+ *
+ * @see af_afi
+ */
+ public af_afi afi; // required
+ /**
+ *
+ * @see af_safi
+ */
+ public af_safi safi; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ PEER_IP((short)1, "peerIp"),
+ /**
+ *
+ * @see af_afi
+ */
+ AFI((short)2, "afi"),
+ /**
+ *
+ * @see af_safi
+ */
+ SAFI((short)3, "safi");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // PEER_IP
+ return PEER_IP;
+ case 2: // AFI
+ return AFI;
+ case 3: // SAFI
+ return SAFI;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.PEER_IP, new org.apache.thrift.meta_data.FieldMetaData("peerIp", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ tmpMap.put(_Fields.AFI, new org.apache.thrift.meta_data.FieldMetaData("afi", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.EnumMetaData(org.apache.thrift.protocol.TType.ENUM, af_afi.class)));
+ tmpMap.put(_Fields.SAFI, new org.apache.thrift.meta_data.FieldMetaData("safi", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.EnumMetaData(org.apache.thrift.protocol.TType.ENUM, af_safi.class)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(enableAddressFamily_args.class, metaDataMap);
+ }
+
+ public enableAddressFamily_args() {
+ }
+
+ public enableAddressFamily_args(
+ String peerIp,
+ af_afi afi,
+ af_safi safi)
+ {
+ this();
+ this.peerIp = peerIp;
+ this.afi = afi;
+ this.safi = safi;
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public enableAddressFamily_args(enableAddressFamily_args other) {
+ if (other.isSetPeerIp()) {
+ this.peerIp = other.peerIp;
+ }
+ if (other.isSetAfi()) {
+ this.afi = other.afi;
+ }
+ if (other.isSetSafi()) {
+ this.safi = other.safi;
+ }
+ }
+
+ public enableAddressFamily_args deepCopy() {
+ return new enableAddressFamily_args(this);
+ }
+
+ @Override
+ public void clear() {
+ this.peerIp = null;
+ this.afi = null;
+ this.safi = null;
+ }
+
+ public String getPeerIp() {
+ return this.peerIp;
+ }
+
+ public enableAddressFamily_args setPeerIp(String peerIp) {
+ this.peerIp = peerIp;
+ return this;
+ }
+
+ public void unsetPeerIp() {
+ this.peerIp = null;
+ }
+
+ /** Returns true if field peerIp is set (has been assigned a value) and false otherwise */
+ public boolean isSetPeerIp() {
+ return this.peerIp != null;
+ }
+
+ public void setPeerIpIsSet(boolean value) {
+ if (!value) {
+ this.peerIp = null;
+ }
+ }
+
+ /**
+ *
+ * @see af_afi
+ */
+ public af_afi getAfi() {
+ return this.afi;
+ }
+
+ /**
+ *
+ * @see af_afi
+ */
+ public enableAddressFamily_args setAfi(af_afi afi) {
+ this.afi = afi;
+ return this;
+ }
+
+ public void unsetAfi() {
+ this.afi = null;
+ }
+
+ /** Returns true if field afi is set (has been assigned a value) and false otherwise */
+ public boolean isSetAfi() {
+ return this.afi != null;
+ }
+
+ public void setAfiIsSet(boolean value) {
+ if (!value) {
+ this.afi = null;
+ }
+ }
+
+ /**
+ *
+ * @see af_safi
+ */
+ public af_safi getSafi() {
+ return this.safi;
+ }
+
+ /**
+ *
+ * @see af_safi
+ */
+ public enableAddressFamily_args setSafi(af_safi safi) {
+ this.safi = safi;
+ return this;
+ }
+
+ public void unsetSafi() {
+ this.safi = null;
+ }
+
+ /** Returns true if field safi is set (has been assigned a value) and false otherwise */
+ public boolean isSetSafi() {
+ return this.safi != null;
+ }
+
+ public void setSafiIsSet(boolean value) {
+ if (!value) {
+ this.safi = null;
+ }
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case PEER_IP:
+ if (value == null) {
+ unsetPeerIp();
+ } else {
+ setPeerIp((String)value);
+ }
+ break;
+
+ case AFI:
+ if (value == null) {
+ unsetAfi();
+ } else {
+ setAfi((af_afi)value);
+ }
+ break;
+
+ case SAFI:
+ if (value == null) {
+ unsetSafi();
+ } else {
+ setSafi((af_safi)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case PEER_IP:
+ return getPeerIp();
+
+ case AFI:
+ return getAfi();
+
+ case SAFI:
+ return getSafi();
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case PEER_IP:
+ return isSetPeerIp();
+ case AFI:
+ return isSetAfi();
+ case SAFI:
+ return isSetSafi();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof enableAddressFamily_args)
+ return this.equals((enableAddressFamily_args)that);
+ return false;
+ }
+
+ public boolean equals(enableAddressFamily_args that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_peerIp = true && this.isSetPeerIp();
+ boolean that_present_peerIp = true && that.isSetPeerIp();
+ if (this_present_peerIp || that_present_peerIp) {
+ if (!(this_present_peerIp && that_present_peerIp))
+ return false;
+ if (!this.peerIp.equals(that.peerIp))
+ return false;
+ }
+
+ boolean this_present_afi = true && this.isSetAfi();
+ boolean that_present_afi = true && that.isSetAfi();
+ if (this_present_afi || that_present_afi) {
+ if (!(this_present_afi && that_present_afi))
+ return false;
+ if (!this.afi.equals(that.afi))
+ return false;
+ }
+
+ boolean this_present_safi = true && this.isSetSafi();
+ boolean that_present_safi = true && that.isSetSafi();
+ if (this_present_safi || that_present_safi) {
+ if (!(this_present_safi && that_present_safi))
+ return false;
+ if (!this.safi.equals(that.safi))
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(enableAddressFamily_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetPeerIp()).compareTo(other.isSetPeerIp());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetPeerIp()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.peerIp, other.peerIp);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetAfi()).compareTo(other.isSetAfi());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetAfi()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.afi, other.afi);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetSafi()).compareTo(other.isSetSafi());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSafi()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.safi, other.safi);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("enableAddressFamily_args(");
+ boolean first = true;
+
+ sb.append("peerIp:");
+ if (this.peerIp == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.peerIp);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("afi:");
+ if (this.afi == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.afi);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("safi:");
+ if (this.safi == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.safi);
+ }
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class enableAddressFamily_argsStandardSchemeFactory implements SchemeFactory {
+ public enableAddressFamily_argsStandardScheme getScheme() {
+ return new enableAddressFamily_argsStandardScheme();
+ }
+ }
+
+ private static class enableAddressFamily_argsStandardScheme extends StandardScheme<enableAddressFamily_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, enableAddressFamily_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // PEER_IP
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.peerIp = iprot.readString();
+ struct.setPeerIpIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 2: // AFI
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.afi = af_afi.findByValue(iprot.readI32());
+ struct.setAfiIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 3: // SAFI
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.safi = af_safi.findByValue(iprot.readI32());
+ struct.setSafiIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, enableAddressFamily_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.peerIp != null) {
+ oprot.writeFieldBegin(PEER_IP_FIELD_DESC);
+ oprot.writeString(struct.peerIp);
+ oprot.writeFieldEnd();
+ }
+ if (struct.afi != null) {
+ oprot.writeFieldBegin(AFI_FIELD_DESC);
+ oprot.writeI32(struct.afi.getValue());
+ oprot.writeFieldEnd();
+ }
+ if (struct.safi != null) {
+ oprot.writeFieldBegin(SAFI_FIELD_DESC);
+ oprot.writeI32(struct.safi.getValue());
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class enableAddressFamily_argsTupleSchemeFactory implements SchemeFactory {
+ public enableAddressFamily_argsTupleScheme getScheme() {
+ return new enableAddressFamily_argsTupleScheme();
+ }
+ }
+
+ private static class enableAddressFamily_argsTupleScheme extends TupleScheme<enableAddressFamily_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, enableAddressFamily_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetPeerIp()) {
+ optionals.set(0);
+ }
+ if (struct.isSetAfi()) {
+ optionals.set(1);
+ }
+ if (struct.isSetSafi()) {
+ optionals.set(2);
+ }
+ oprot.writeBitSet(optionals, 3);
+ if (struct.isSetPeerIp()) {
+ oprot.writeString(struct.peerIp);
+ }
+ if (struct.isSetAfi()) {
+ oprot.writeI32(struct.afi.getValue());
+ }
+ if (struct.isSetSafi()) {
+ oprot.writeI32(struct.safi.getValue());
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, enableAddressFamily_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(3);
+ if (incoming.get(0)) {
+ struct.peerIp = iprot.readString();
+ struct.setPeerIpIsSet(true);
+ }
+ if (incoming.get(1)) {
+ struct.afi = af_afi.findByValue(iprot.readI32());
+ struct.setAfiIsSet(true);
+ }
+ if (incoming.get(2)) {
+ struct.safi = af_safi.findByValue(iprot.readI32());
+ struct.setSafiIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class enableAddressFamily_result implements org.apache.thrift.TBase<enableAddressFamily_result, enableAddressFamily_result._Fields>, java.io.Serializable, Cloneable, Comparable<enableAddressFamily_result> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("enableAddressFamily_result");
+
+ private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new enableAddressFamily_resultStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new enableAddressFamily_resultTupleSchemeFactory());
+ }
+
+ public int success; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ SUCCESS((short)0, "success");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 0: // SUCCESS
+ return SUCCESS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __SUCCESS_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(enableAddressFamily_result.class, metaDataMap);
+ }
+
+ public enableAddressFamily_result() {
+ }
+
+ public enableAddressFamily_result(
+ int success)
+ {
+ this();
+ this.success = success;
+ setSuccessIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public enableAddressFamily_result(enableAddressFamily_result other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.success = other.success;
+ }
+
+ public enableAddressFamily_result deepCopy() {
+ return new enableAddressFamily_result(this);
+ }
+
+ @Override
+ public void clear() {
+ setSuccessIsSet(false);
+ this.success = 0;
+ }
+
+ public int getSuccess() {
+ return this.success;
+ }
+
+ public enableAddressFamily_result setSuccess(int success) {
+ this.success = success;
+ setSuccessIsSet(true);
+ return this;
+ }
+
+ public void unsetSuccess() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ /** Returns true if field success is set (has been assigned a value) and false otherwise */
+ public boolean isSetSuccess() {
+ return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ public void setSuccessIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case SUCCESS:
+ if (value == null) {
+ unsetSuccess();
+ } else {
+ setSuccess((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case SUCCESS:
+ return Integer.valueOf(getSuccess());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case SUCCESS:
+ return isSetSuccess();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof enableAddressFamily_result)
+ return this.equals((enableAddressFamily_result)that);
+ return false;
+ }
+
+ public boolean equals(enableAddressFamily_result that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_success = true;
+ boolean that_present_success = true;
+ if (this_present_success || that_present_success) {
+ if (!(this_present_success && that_present_success))
+ return false;
+ if (this.success != that.success)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(enableAddressFamily_result other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSuccess()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("enableAddressFamily_result(");
+ boolean first = true;
+
+ sb.append("success:");
+ sb.append(this.success);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class enableAddressFamily_resultStandardSchemeFactory implements SchemeFactory {
+ public enableAddressFamily_resultStandardScheme getScheme() {
+ return new enableAddressFamily_resultStandardScheme();
+ }
+ }
+
+ private static class enableAddressFamily_resultStandardScheme extends StandardScheme<enableAddressFamily_result> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, enableAddressFamily_result struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 0: // SUCCESS
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, enableAddressFamily_result struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.isSetSuccess()) {
+ oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+ oprot.writeI32(struct.success);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class enableAddressFamily_resultTupleSchemeFactory implements SchemeFactory {
+ public enableAddressFamily_resultTupleScheme getScheme() {
+ return new enableAddressFamily_resultTupleScheme();
+ }
+ }
+
+ private static class enableAddressFamily_resultTupleScheme extends TupleScheme<enableAddressFamily_result> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, enableAddressFamily_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetSuccess()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetSuccess()) {
+ oprot.writeI32(struct.success);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, enableAddressFamily_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class disableAddressFamily_args implements org.apache.thrift.TBase<disableAddressFamily_args, disableAddressFamily_args._Fields>, java.io.Serializable, Cloneable, Comparable<disableAddressFamily_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("disableAddressFamily_args");
+
+ private static final org.apache.thrift.protocol.TField PEER_IP_FIELD_DESC = new org.apache.thrift.protocol.TField("peerIp", org.apache.thrift.protocol.TType.STRING, (short)1);
+ private static final org.apache.thrift.protocol.TField AFI_FIELD_DESC = new org.apache.thrift.protocol.TField("afi", org.apache.thrift.protocol.TType.I32, (short)2);
+ private static final org.apache.thrift.protocol.TField SAFI_FIELD_DESC = new org.apache.thrift.protocol.TField("safi", org.apache.thrift.protocol.TType.I32, (short)3);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new disableAddressFamily_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new disableAddressFamily_argsTupleSchemeFactory());
+ }
+
+ public String peerIp; // required
+ /**
+ *
+ * @see af_afi
+ */
+ public af_afi afi; // required
+ /**
+ *
+ * @see af_safi
+ */
+ public af_safi safi; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ PEER_IP((short)1, "peerIp"),
+ /**
+ *
+ * @see af_afi
+ */
+ AFI((short)2, "afi"),
+ /**
+ *
+ * @see af_safi
+ */
+ SAFI((short)3, "safi");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // PEER_IP
+ return PEER_IP;
+ case 2: // AFI
+ return AFI;
+ case 3: // SAFI
+ return SAFI;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.PEER_IP, new org.apache.thrift.meta_data.FieldMetaData("peerIp", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ tmpMap.put(_Fields.AFI, new org.apache.thrift.meta_data.FieldMetaData("afi", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.EnumMetaData(org.apache.thrift.protocol.TType.ENUM, af_afi.class)));
+ tmpMap.put(_Fields.SAFI, new org.apache.thrift.meta_data.FieldMetaData("safi", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.EnumMetaData(org.apache.thrift.protocol.TType.ENUM, af_safi.class)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(disableAddressFamily_args.class, metaDataMap);
+ }
+
+ public disableAddressFamily_args() {
+ }
+
+ public disableAddressFamily_args(
+ String peerIp,
+ af_afi afi,
+ af_safi safi)
+ {
+ this();
+ this.peerIp = peerIp;
+ this.afi = afi;
+ this.safi = safi;
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public disableAddressFamily_args(disableAddressFamily_args other) {
+ if (other.isSetPeerIp()) {
+ this.peerIp = other.peerIp;
+ }
+ if (other.isSetAfi()) {
+ this.afi = other.afi;
+ }
+ if (other.isSetSafi()) {
+ this.safi = other.safi;
+ }
+ }
+
+ public disableAddressFamily_args deepCopy() {
+ return new disableAddressFamily_args(this);
+ }
+
+ @Override
+ public void clear() {
+ this.peerIp = null;
+ this.afi = null;
+ this.safi = null;
+ }
+
+ public String getPeerIp() {
+ return this.peerIp;
+ }
+
+ public disableAddressFamily_args setPeerIp(String peerIp) {
+ this.peerIp = peerIp;
+ return this;
+ }
+
+ public void unsetPeerIp() {
+ this.peerIp = null;
+ }
+
+ /** Returns true if field peerIp is set (has been assigned a value) and false otherwise */
+ public boolean isSetPeerIp() {
+ return this.peerIp != null;
+ }
+
+ public void setPeerIpIsSet(boolean value) {
+ if (!value) {
+ this.peerIp = null;
+ }
+ }
+
+ /**
+ *
+ * @see af_afi
+ */
+ public af_afi getAfi() {
+ return this.afi;
+ }
+
+ /**
+ *
+ * @see af_afi
+ */
+ public disableAddressFamily_args setAfi(af_afi afi) {
+ this.afi = afi;
+ return this;
+ }
+
+ public void unsetAfi() {
+ this.afi = null;
+ }
+
+ /** Returns true if field afi is set (has been assigned a value) and false otherwise */
+ public boolean isSetAfi() {
+ return this.afi != null;
+ }
+
+ public void setAfiIsSet(boolean value) {
+ if (!value) {
+ this.afi = null;
+ }
+ }
+
+ /**
+ *
+ * @see af_safi
+ */
+ public af_safi getSafi() {
+ return this.safi;
+ }
+
+ /**
+ *
+ * @see af_safi
+ */
+ public disableAddressFamily_args setSafi(af_safi safi) {
+ this.safi = safi;
+ return this;
+ }
+
+ public void unsetSafi() {
+ this.safi = null;
+ }
+
+ /** Returns true if field safi is set (has been assigned a value) and false otherwise */
+ public boolean isSetSafi() {
+ return this.safi != null;
+ }
+
+ public void setSafiIsSet(boolean value) {
+ if (!value) {
+ this.safi = null;
+ }
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case PEER_IP:
+ if (value == null) {
+ unsetPeerIp();
+ } else {
+ setPeerIp((String)value);
+ }
+ break;
+
+ case AFI:
+ if (value == null) {
+ unsetAfi();
+ } else {
+ setAfi((af_afi)value);
+ }
+ break;
+
+ case SAFI:
+ if (value == null) {
+ unsetSafi();
+ } else {
+ setSafi((af_safi)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case PEER_IP:
+ return getPeerIp();
+
+ case AFI:
+ return getAfi();
+
+ case SAFI:
+ return getSafi();
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case PEER_IP:
+ return isSetPeerIp();
+ case AFI:
+ return isSetAfi();
+ case SAFI:
+ return isSetSafi();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof disableAddressFamily_args)
+ return this.equals((disableAddressFamily_args)that);
+ return false;
+ }
+
+ public boolean equals(disableAddressFamily_args that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_peerIp = true && this.isSetPeerIp();
+ boolean that_present_peerIp = true && that.isSetPeerIp();
+ if (this_present_peerIp || that_present_peerIp) {
+ if (!(this_present_peerIp && that_present_peerIp))
+ return false;
+ if (!this.peerIp.equals(that.peerIp))
+ return false;
+ }
+
+ boolean this_present_afi = true && this.isSetAfi();
+ boolean that_present_afi = true && that.isSetAfi();
+ if (this_present_afi || that_present_afi) {
+ if (!(this_present_afi && that_present_afi))
+ return false;
+ if (!this.afi.equals(that.afi))
+ return false;
+ }
+
+ boolean this_present_safi = true && this.isSetSafi();
+ boolean that_present_safi = true && that.isSetSafi();
+ if (this_present_safi || that_present_safi) {
+ if (!(this_present_safi && that_present_safi))
+ return false;
+ if (!this.safi.equals(that.safi))
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(disableAddressFamily_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetPeerIp()).compareTo(other.isSetPeerIp());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetPeerIp()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.peerIp, other.peerIp);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetAfi()).compareTo(other.isSetAfi());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetAfi()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.afi, other.afi);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetSafi()).compareTo(other.isSetSafi());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSafi()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.safi, other.safi);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("disableAddressFamily_args(");
+ boolean first = true;
+
+ sb.append("peerIp:");
+ if (this.peerIp == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.peerIp);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("afi:");
+ if (this.afi == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.afi);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("safi:");
+ if (this.safi == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.safi);
+ }
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class disableAddressFamily_argsStandardSchemeFactory implements SchemeFactory {
+ public disableAddressFamily_argsStandardScheme getScheme() {
+ return new disableAddressFamily_argsStandardScheme();
+ }
+ }
+
+ private static class disableAddressFamily_argsStandardScheme extends StandardScheme<disableAddressFamily_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, disableAddressFamily_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // PEER_IP
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.peerIp = iprot.readString();
+ struct.setPeerIpIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 2: // AFI
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.afi = af_afi.findByValue(iprot.readI32());
+ struct.setAfiIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 3: // SAFI
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.safi = af_safi.findByValue(iprot.readI32());
+ struct.setSafiIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, disableAddressFamily_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.peerIp != null) {
+ oprot.writeFieldBegin(PEER_IP_FIELD_DESC);
+ oprot.writeString(struct.peerIp);
+ oprot.writeFieldEnd();
+ }
+ if (struct.afi != null) {
+ oprot.writeFieldBegin(AFI_FIELD_DESC);
+ oprot.writeI32(struct.afi.getValue());
+ oprot.writeFieldEnd();
+ }
+ if (struct.safi != null) {
+ oprot.writeFieldBegin(SAFI_FIELD_DESC);
+ oprot.writeI32(struct.safi.getValue());
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class disableAddressFamily_argsTupleSchemeFactory implements SchemeFactory {
+ public disableAddressFamily_argsTupleScheme getScheme() {
+ return new disableAddressFamily_argsTupleScheme();
+ }
+ }
+
+ private static class disableAddressFamily_argsTupleScheme extends TupleScheme<disableAddressFamily_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, disableAddressFamily_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetPeerIp()) {
+ optionals.set(0);
+ }
+ if (struct.isSetAfi()) {
+ optionals.set(1);
+ }
+ if (struct.isSetSafi()) {
+ optionals.set(2);
+ }
+ oprot.writeBitSet(optionals, 3);
+ if (struct.isSetPeerIp()) {
+ oprot.writeString(struct.peerIp);
+ }
+ if (struct.isSetAfi()) {
+ oprot.writeI32(struct.afi.getValue());
+ }
+ if (struct.isSetSafi()) {
+ oprot.writeI32(struct.safi.getValue());
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, disableAddressFamily_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(3);
+ if (incoming.get(0)) {
+ struct.peerIp = iprot.readString();
+ struct.setPeerIpIsSet(true);
+ }
+ if (incoming.get(1)) {
+ struct.afi = af_afi.findByValue(iprot.readI32());
+ struct.setAfiIsSet(true);
+ }
+ if (incoming.get(2)) {
+ struct.safi = af_safi.findByValue(iprot.readI32());
+ struct.setSafiIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class disableAddressFamily_result implements org.apache.thrift.TBase<disableAddressFamily_result, disableAddressFamily_result._Fields>, java.io.Serializable, Cloneable, Comparable<disableAddressFamily_result> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("disableAddressFamily_result");
+
+ private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new disableAddressFamily_resultStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new disableAddressFamily_resultTupleSchemeFactory());
+ }
+
+ public int success; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ SUCCESS((short)0, "success");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 0: // SUCCESS
+ return SUCCESS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __SUCCESS_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(disableAddressFamily_result.class, metaDataMap);
+ }
+
+ public disableAddressFamily_result() {
+ }
+
+ public disableAddressFamily_result(
+ int success)
+ {
+ this();
+ this.success = success;
+ setSuccessIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public disableAddressFamily_result(disableAddressFamily_result other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.success = other.success;
+ }
+
+ public disableAddressFamily_result deepCopy() {
+ return new disableAddressFamily_result(this);
+ }
+
+ @Override
+ public void clear() {
+ setSuccessIsSet(false);
+ this.success = 0;
+ }
+
+ public int getSuccess() {
+ return this.success;
+ }
+
+ public disableAddressFamily_result setSuccess(int success) {
+ this.success = success;
+ setSuccessIsSet(true);
+ return this;
+ }
+
+ public void unsetSuccess() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ /** Returns true if field success is set (has been assigned a value) and false otherwise */
+ public boolean isSetSuccess() {
+ return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ public void setSuccessIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case SUCCESS:
+ if (value == null) {
+ unsetSuccess();
+ } else {
+ setSuccess((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case SUCCESS:
+ return Integer.valueOf(getSuccess());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case SUCCESS:
+ return isSetSuccess();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof disableAddressFamily_result)
+ return this.equals((disableAddressFamily_result)that);
+ return false;
+ }
+
+ public boolean equals(disableAddressFamily_result that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_success = true;
+ boolean that_present_success = true;
+ if (this_present_success || that_present_success) {
+ if (!(this_present_success && that_present_success))
+ return false;
+ if (this.success != that.success)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(disableAddressFamily_result other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSuccess()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("disableAddressFamily_result(");
+ boolean first = true;
+
+ sb.append("success:");
+ sb.append(this.success);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class disableAddressFamily_resultStandardSchemeFactory implements SchemeFactory {
+ public disableAddressFamily_resultStandardScheme getScheme() {
+ return new disableAddressFamily_resultStandardScheme();
+ }
+ }
+
+ private static class disableAddressFamily_resultStandardScheme extends StandardScheme<disableAddressFamily_result> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, disableAddressFamily_result struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 0: // SUCCESS
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, disableAddressFamily_result struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.isSetSuccess()) {
+ oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+ oprot.writeI32(struct.success);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class disableAddressFamily_resultTupleSchemeFactory implements SchemeFactory {
+ public disableAddressFamily_resultTupleScheme getScheme() {
+ return new disableAddressFamily_resultTupleScheme();
+ }
+ }
+
+ private static class disableAddressFamily_resultTupleScheme extends TupleScheme<disableAddressFamily_result> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, disableAddressFamily_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetSuccess()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetSuccess()) {
+ oprot.writeI32(struct.success);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, disableAddressFamily_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class setLogConfig_args implements org.apache.thrift.TBase<setLogConfig_args, setLogConfig_args._Fields>, java.io.Serializable, Cloneable, Comparable<setLogConfig_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("setLogConfig_args");
+
+ private static final org.apache.thrift.protocol.TField LOG_FILE_NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("logFileName", org.apache.thrift.protocol.TType.STRING, (short)1);
+ private static final org.apache.thrift.protocol.TField LOG_LEVEL_FIELD_DESC = new org.apache.thrift.protocol.TField("logLevel", org.apache.thrift.protocol.TType.STRING, (short)2);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new setLogConfig_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new setLogConfig_argsTupleSchemeFactory());
+ }
+
+ public String logFileName; // required
+ public String logLevel; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ LOG_FILE_NAME((short)1, "logFileName"),
+ LOG_LEVEL((short)2, "logLevel");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // LOG_FILE_NAME
+ return LOG_FILE_NAME;
+ case 2: // LOG_LEVEL
+ return LOG_LEVEL;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.LOG_FILE_NAME, new org.apache.thrift.meta_data.FieldMetaData("logFileName", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ tmpMap.put(_Fields.LOG_LEVEL, new org.apache.thrift.meta_data.FieldMetaData("logLevel", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(setLogConfig_args.class, metaDataMap);
+ }
+
+ public setLogConfig_args() {
+ }
+
+ public setLogConfig_args(
+ String logFileName,
+ String logLevel)
+ {
+ this();
+ this.logFileName = logFileName;
+ this.logLevel = logLevel;
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public setLogConfig_args(setLogConfig_args other) {
+ if (other.isSetLogFileName()) {
+ this.logFileName = other.logFileName;
+ }
+ if (other.isSetLogLevel()) {
+ this.logLevel = other.logLevel;
+ }
+ }
+
+ public setLogConfig_args deepCopy() {
+ return new setLogConfig_args(this);
+ }
+
+ @Override
+ public void clear() {
+ this.logFileName = null;
+ this.logLevel = null;
+ }
+
+ public String getLogFileName() {
+ return this.logFileName;
+ }
+
+ public setLogConfig_args setLogFileName(String logFileName) {
+ this.logFileName = logFileName;
+ return this;
+ }
+
+ public void unsetLogFileName() {
+ this.logFileName = null;
+ }
+
+ /** Returns true if field logFileName is set (has been assigned a value) and false otherwise */
+ public boolean isSetLogFileName() {
+ return this.logFileName != null;
+ }
+
+ public void setLogFileNameIsSet(boolean value) {
+ if (!value) {
+ this.logFileName = null;
+ }
+ }
+
+ public String getLogLevel() {
+ return this.logLevel;
+ }
+
+ public setLogConfig_args setLogLevel(String logLevel) {
+ this.logLevel = logLevel;
+ return this;
+ }
+
+ public void unsetLogLevel() {
+ this.logLevel = null;
+ }
+
+ /** Returns true if field logLevel is set (has been assigned a value) and false otherwise */
+ public boolean isSetLogLevel() {
+ return this.logLevel != null;
+ }
+
+ public void setLogLevelIsSet(boolean value) {
+ if (!value) {
+ this.logLevel = null;
+ }
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case LOG_FILE_NAME:
+ if (value == null) {
+ unsetLogFileName();
+ } else {
+ setLogFileName((String)value);
+ }
+ break;
+
+ case LOG_LEVEL:
+ if (value == null) {
+ unsetLogLevel();
+ } else {
+ setLogLevel((String)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case LOG_FILE_NAME:
+ return getLogFileName();
+
+ case LOG_LEVEL:
+ return getLogLevel();
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case LOG_FILE_NAME:
+ return isSetLogFileName();
+ case LOG_LEVEL:
+ return isSetLogLevel();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof setLogConfig_args)
+ return this.equals((setLogConfig_args)that);
+ return false;
+ }
+
+ public boolean equals(setLogConfig_args that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_logFileName = true && this.isSetLogFileName();
+ boolean that_present_logFileName = true && that.isSetLogFileName();
+ if (this_present_logFileName || that_present_logFileName) {
+ if (!(this_present_logFileName && that_present_logFileName))
+ return false;
+ if (!this.logFileName.equals(that.logFileName))
+ return false;
+ }
+
+ boolean this_present_logLevel = true && this.isSetLogLevel();
+ boolean that_present_logLevel = true && that.isSetLogLevel();
+ if (this_present_logLevel || that_present_logLevel) {
+ if (!(this_present_logLevel && that_present_logLevel))
+ return false;
+ if (!this.logLevel.equals(that.logLevel))
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(setLogConfig_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetLogFileName()).compareTo(other.isSetLogFileName());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetLogFileName()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.logFileName, other.logFileName);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetLogLevel()).compareTo(other.isSetLogLevel());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetLogLevel()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.logLevel, other.logLevel);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("setLogConfig_args(");
+ boolean first = true;
+
+ sb.append("logFileName:");
+ if (this.logFileName == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.logFileName);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("logLevel:");
+ if (this.logLevel == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.logLevel);
+ }
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class setLogConfig_argsStandardSchemeFactory implements SchemeFactory {
+ public setLogConfig_argsStandardScheme getScheme() {
+ return new setLogConfig_argsStandardScheme();
+ }
+ }
+
+ private static class setLogConfig_argsStandardScheme extends StandardScheme<setLogConfig_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, setLogConfig_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // LOG_FILE_NAME
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.logFileName = iprot.readString();
+ struct.setLogFileNameIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 2: // LOG_LEVEL
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.logLevel = iprot.readString();
+ struct.setLogLevelIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, setLogConfig_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.logFileName != null) {
+ oprot.writeFieldBegin(LOG_FILE_NAME_FIELD_DESC);
+ oprot.writeString(struct.logFileName);
+ oprot.writeFieldEnd();
+ }
+ if (struct.logLevel != null) {
+ oprot.writeFieldBegin(LOG_LEVEL_FIELD_DESC);
+ oprot.writeString(struct.logLevel);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class setLogConfig_argsTupleSchemeFactory implements SchemeFactory {
+ public setLogConfig_argsTupleScheme getScheme() {
+ return new setLogConfig_argsTupleScheme();
+ }
+ }
+
+ private static class setLogConfig_argsTupleScheme extends TupleScheme<setLogConfig_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, setLogConfig_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetLogFileName()) {
+ optionals.set(0);
+ }
+ if (struct.isSetLogLevel()) {
+ optionals.set(1);
+ }
+ oprot.writeBitSet(optionals, 2);
+ if (struct.isSetLogFileName()) {
+ oprot.writeString(struct.logFileName);
+ }
+ if (struct.isSetLogLevel()) {
+ oprot.writeString(struct.logLevel);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, setLogConfig_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(2);
+ if (incoming.get(0)) {
+ struct.logFileName = iprot.readString();
+ struct.setLogFileNameIsSet(true);
+ }
+ if (incoming.get(1)) {
+ struct.logLevel = iprot.readString();
+ struct.setLogLevelIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class setLogConfig_result implements org.apache.thrift.TBase<setLogConfig_result, setLogConfig_result._Fields>, java.io.Serializable, Cloneable, Comparable<setLogConfig_result> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("setLogConfig_result");
+
+ private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new setLogConfig_resultStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new setLogConfig_resultTupleSchemeFactory());
+ }
+
+ public int success; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ SUCCESS((short)0, "success");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 0: // SUCCESS
+ return SUCCESS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __SUCCESS_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(setLogConfig_result.class, metaDataMap);
+ }
+
+ public setLogConfig_result() {
+ }
+
+ public setLogConfig_result(
+ int success)
+ {
+ this();
+ this.success = success;
+ setSuccessIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public setLogConfig_result(setLogConfig_result other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.success = other.success;
+ }
+
+ public setLogConfig_result deepCopy() {
+ return new setLogConfig_result(this);
+ }
+
+ @Override
+ public void clear() {
+ setSuccessIsSet(false);
+ this.success = 0;
+ }
+
+ public int getSuccess() {
+ return this.success;
+ }
+
+ public setLogConfig_result setSuccess(int success) {
+ this.success = success;
+ setSuccessIsSet(true);
+ return this;
+ }
+
+ public void unsetSuccess() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ /** Returns true if field success is set (has been assigned a value) and false otherwise */
+ public boolean isSetSuccess() {
+ return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ public void setSuccessIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case SUCCESS:
+ if (value == null) {
+ unsetSuccess();
+ } else {
+ setSuccess((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case SUCCESS:
+ return Integer.valueOf(getSuccess());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case SUCCESS:
+ return isSetSuccess();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof setLogConfig_result)
+ return this.equals((setLogConfig_result)that);
+ return false;
+ }
+
+ public boolean equals(setLogConfig_result that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_success = true;
+ boolean that_present_success = true;
+ if (this_present_success || that_present_success) {
+ if (!(this_present_success && that_present_success))
+ return false;
+ if (this.success != that.success)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(setLogConfig_result other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSuccess()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("setLogConfig_result(");
+ boolean first = true;
+
+ sb.append("success:");
+ sb.append(this.success);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class setLogConfig_resultStandardSchemeFactory implements SchemeFactory {
+ public setLogConfig_resultStandardScheme getScheme() {
+ return new setLogConfig_resultStandardScheme();
+ }
+ }
+
+ private static class setLogConfig_resultStandardScheme extends StandardScheme<setLogConfig_result> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, setLogConfig_result struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 0: // SUCCESS
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, setLogConfig_result struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.isSetSuccess()) {
+ oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+ oprot.writeI32(struct.success);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class setLogConfig_resultTupleSchemeFactory implements SchemeFactory {
+ public setLogConfig_resultTupleScheme getScheme() {
+ return new setLogConfig_resultTupleScheme();
+ }
+ }
+
+ private static class setLogConfig_resultTupleScheme extends TupleScheme<setLogConfig_result> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, setLogConfig_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetSuccess()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetSuccess()) {
+ oprot.writeI32(struct.success);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, setLogConfig_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class enableGracefulRestart_args implements org.apache.thrift.TBase<enableGracefulRestart_args, enableGracefulRestart_args._Fields>, java.io.Serializable, Cloneable, Comparable<enableGracefulRestart_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("enableGracefulRestart_args");
+
+ private static final org.apache.thrift.protocol.TField STALEPATH_TIME_FIELD_DESC = new org.apache.thrift.protocol.TField("stalepathTime", org.apache.thrift.protocol.TType.I32, (short)1);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new enableGracefulRestart_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new enableGracefulRestart_argsTupleSchemeFactory());
+ }
+
+ public int stalepathTime; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ STALEPATH_TIME((short)1, "stalepathTime");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // STALEPATH_TIME
+ return STALEPATH_TIME;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __STALEPATHTIME_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.STALEPATH_TIME, new org.apache.thrift.meta_data.FieldMetaData("stalepathTime", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(enableGracefulRestart_args.class, metaDataMap);
+ }
+
+ public enableGracefulRestart_args() {
+ }
+
+ public enableGracefulRestart_args(
+ int stalepathTime)
+ {
+ this();
+ this.stalepathTime = stalepathTime;
+ setStalepathTimeIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public enableGracefulRestart_args(enableGracefulRestart_args other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.stalepathTime = other.stalepathTime;
+ }
+
+ public enableGracefulRestart_args deepCopy() {
+ return new enableGracefulRestart_args(this);
+ }
+
+ @Override
+ public void clear() {
+ setStalepathTimeIsSet(false);
+ this.stalepathTime = 0;
+ }
+
+ public int getStalepathTime() {
+ return this.stalepathTime;
+ }
+
+ public enableGracefulRestart_args setStalepathTime(int stalepathTime) {
+ this.stalepathTime = stalepathTime;
+ setStalepathTimeIsSet(true);
+ return this;
+ }
+
+ public void unsetStalepathTime() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __STALEPATHTIME_ISSET_ID);
+ }
+
+ /** Returns true if field stalepathTime is set (has been assigned a value) and false otherwise */
+ public boolean isSetStalepathTime() {
+ return EncodingUtils.testBit(__isset_bitfield, __STALEPATHTIME_ISSET_ID);
+ }
+
+ public void setStalepathTimeIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __STALEPATHTIME_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case STALEPATH_TIME:
+ if (value == null) {
+ unsetStalepathTime();
+ } else {
+ setStalepathTime((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case STALEPATH_TIME:
+ return Integer.valueOf(getStalepathTime());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case STALEPATH_TIME:
+ return isSetStalepathTime();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof enableGracefulRestart_args)
+ return this.equals((enableGracefulRestart_args)that);
+ return false;
+ }
+
+ public boolean equals(enableGracefulRestart_args that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_stalepathTime = true;
+ boolean that_present_stalepathTime = true;
+ if (this_present_stalepathTime || that_present_stalepathTime) {
+ if (!(this_present_stalepathTime && that_present_stalepathTime))
+ return false;
+ if (this.stalepathTime != that.stalepathTime)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(enableGracefulRestart_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetStalepathTime()).compareTo(other.isSetStalepathTime());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetStalepathTime()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.stalepathTime, other.stalepathTime);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("enableGracefulRestart_args(");
+ boolean first = true;
+
+ sb.append("stalepathTime:");
+ sb.append(this.stalepathTime);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class enableGracefulRestart_argsStandardSchemeFactory implements SchemeFactory {
+ public enableGracefulRestart_argsStandardScheme getScheme() {
+ return new enableGracefulRestart_argsStandardScheme();
+ }
+ }
+
+ private static class enableGracefulRestart_argsStandardScheme extends StandardScheme<enableGracefulRestart_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, enableGracefulRestart_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // STALEPATH_TIME
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.stalepathTime = iprot.readI32();
+ struct.setStalepathTimeIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, enableGracefulRestart_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ oprot.writeFieldBegin(STALEPATH_TIME_FIELD_DESC);
+ oprot.writeI32(struct.stalepathTime);
+ oprot.writeFieldEnd();
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class enableGracefulRestart_argsTupleSchemeFactory implements SchemeFactory {
+ public enableGracefulRestart_argsTupleScheme getScheme() {
+ return new enableGracefulRestart_argsTupleScheme();
+ }
+ }
+
+ private static class enableGracefulRestart_argsTupleScheme extends TupleScheme<enableGracefulRestart_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, enableGracefulRestart_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetStalepathTime()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetStalepathTime()) {
+ oprot.writeI32(struct.stalepathTime);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, enableGracefulRestart_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.stalepathTime = iprot.readI32();
+ struct.setStalepathTimeIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class enableGracefulRestart_result implements org.apache.thrift.TBase<enableGracefulRestart_result, enableGracefulRestart_result._Fields>, java.io.Serializable, Cloneable, Comparable<enableGracefulRestart_result> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("enableGracefulRestart_result");
+
+ private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new enableGracefulRestart_resultStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new enableGracefulRestart_resultTupleSchemeFactory());
+ }
+
+ public int success; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ SUCCESS((short)0, "success");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 0: // SUCCESS
+ return SUCCESS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __SUCCESS_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(enableGracefulRestart_result.class, metaDataMap);
+ }
+
+ public enableGracefulRestart_result() {
+ }
+
+ public enableGracefulRestart_result(
+ int success)
+ {
+ this();
+ this.success = success;
+ setSuccessIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public enableGracefulRestart_result(enableGracefulRestart_result other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.success = other.success;
+ }
+
+ public enableGracefulRestart_result deepCopy() {
+ return new enableGracefulRestart_result(this);
+ }
+
+ @Override
+ public void clear() {
+ setSuccessIsSet(false);
+ this.success = 0;
+ }
+
+ public int getSuccess() {
+ return this.success;
+ }
+
+ public enableGracefulRestart_result setSuccess(int success) {
+ this.success = success;
+ setSuccessIsSet(true);
+ return this;
+ }
+
+ public void unsetSuccess() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ /** Returns true if field success is set (has been assigned a value) and false otherwise */
+ public boolean isSetSuccess() {
+ return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ public void setSuccessIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case SUCCESS:
+ if (value == null) {
+ unsetSuccess();
+ } else {
+ setSuccess((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case SUCCESS:
+ return Integer.valueOf(getSuccess());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case SUCCESS:
+ return isSetSuccess();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof enableGracefulRestart_result)
+ return this.equals((enableGracefulRestart_result)that);
+ return false;
+ }
+
+ public boolean equals(enableGracefulRestart_result that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_success = true;
+ boolean that_present_success = true;
+ if (this_present_success || that_present_success) {
+ if (!(this_present_success && that_present_success))
+ return false;
+ if (this.success != that.success)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(enableGracefulRestart_result other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSuccess()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("enableGracefulRestart_result(");
+ boolean first = true;
+
+ sb.append("success:");
+ sb.append(this.success);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class enableGracefulRestart_resultStandardSchemeFactory implements SchemeFactory {
+ public enableGracefulRestart_resultStandardScheme getScheme() {
+ return new enableGracefulRestart_resultStandardScheme();
+ }
+ }
+
+ private static class enableGracefulRestart_resultStandardScheme extends StandardScheme<enableGracefulRestart_result> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, enableGracefulRestart_result struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 0: // SUCCESS
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, enableGracefulRestart_result struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.isSetSuccess()) {
+ oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+ oprot.writeI32(struct.success);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class enableGracefulRestart_resultTupleSchemeFactory implements SchemeFactory {
+ public enableGracefulRestart_resultTupleScheme getScheme() {
+ return new enableGracefulRestart_resultTupleScheme();
+ }
+ }
+
+ private static class enableGracefulRestart_resultTupleScheme extends TupleScheme<enableGracefulRestart_result> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, enableGracefulRestart_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetSuccess()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetSuccess()) {
+ oprot.writeI32(struct.success);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, enableGracefulRestart_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class disableGracefulRestart_args implements org.apache.thrift.TBase<disableGracefulRestart_args, disableGracefulRestart_args._Fields>, java.io.Serializable, Cloneable, Comparable<disableGracefulRestart_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("disableGracefulRestart_args");
+
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new disableGracefulRestart_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new disableGracefulRestart_argsTupleSchemeFactory());
+ }
+
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+;
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(disableGracefulRestart_args.class, metaDataMap);
+ }
+
+ public disableGracefulRestart_args() {
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public disableGracefulRestart_args(disableGracefulRestart_args other) {
+ }
+
+ public disableGracefulRestart_args deepCopy() {
+ return new disableGracefulRestart_args(this);
+ }
+
+ @Override
+ public void clear() {
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof disableGracefulRestart_args)
+ return this.equals((disableGracefulRestart_args)that);
+ return false;
+ }
+
+ public boolean equals(disableGracefulRestart_args that) {
+ if (that == null)
+ return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(disableGracefulRestart_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("disableGracefulRestart_args(");
+ boolean first = true;
+
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class disableGracefulRestart_argsStandardSchemeFactory implements SchemeFactory {
+ public disableGracefulRestart_argsStandardScheme getScheme() {
+ return new disableGracefulRestart_argsStandardScheme();
+ }
+ }
+
+ private static class disableGracefulRestart_argsStandardScheme extends StandardScheme<disableGracefulRestart_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, disableGracefulRestart_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, disableGracefulRestart_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class disableGracefulRestart_argsTupleSchemeFactory implements SchemeFactory {
+ public disableGracefulRestart_argsTupleScheme getScheme() {
+ return new disableGracefulRestart_argsTupleScheme();
+ }
+ }
+
+ private static class disableGracefulRestart_argsTupleScheme extends TupleScheme<disableGracefulRestart_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, disableGracefulRestart_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, disableGracefulRestart_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ }
+ }
+
+ }
+
+ public static class disableGracefulRestart_result implements org.apache.thrift.TBase<disableGracefulRestart_result, disableGracefulRestart_result._Fields>, java.io.Serializable, Cloneable, Comparable<disableGracefulRestart_result> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("disableGracefulRestart_result");
+
+ private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.I32, (short)0);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new disableGracefulRestart_resultStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new disableGracefulRestart_resultTupleSchemeFactory());
+ }
+
+ public int success; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ SUCCESS((short)0, "success");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 0: // SUCCESS
+ return SUCCESS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __SUCCESS_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(disableGracefulRestart_result.class, metaDataMap);
+ }
+
+ public disableGracefulRestart_result() {
+ }
+
+ public disableGracefulRestart_result(
+ int success)
+ {
+ this();
+ this.success = success;
+ setSuccessIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public disableGracefulRestart_result(disableGracefulRestart_result other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.success = other.success;
+ }
+
+ public disableGracefulRestart_result deepCopy() {
+ return new disableGracefulRestart_result(this);
+ }
+
+ @Override
+ public void clear() {
+ setSuccessIsSet(false);
+ this.success = 0;
+ }
+
+ public int getSuccess() {
+ return this.success;
+ }
+
+ public disableGracefulRestart_result setSuccess(int success) {
+ this.success = success;
+ setSuccessIsSet(true);
+ return this;
+ }
+
+ public void unsetSuccess() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ /** Returns true if field success is set (has been assigned a value) and false otherwise */
+ public boolean isSetSuccess() {
+ return EncodingUtils.testBit(__isset_bitfield, __SUCCESS_ISSET_ID);
+ }
+
+ public void setSuccessIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SUCCESS_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case SUCCESS:
+ if (value == null) {
+ unsetSuccess();
+ } else {
+ setSuccess((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case SUCCESS:
+ return Integer.valueOf(getSuccess());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case SUCCESS:
+ return isSetSuccess();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof disableGracefulRestart_result)
+ return this.equals((disableGracefulRestart_result)that);
+ return false;
+ }
+
+ public boolean equals(disableGracefulRestart_result that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_success = true;
+ boolean that_present_success = true;
+ if (this_present_success || that_present_success) {
+ if (!(this_present_success && that_present_success))
+ return false;
+ if (this.success != that.success)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(disableGracefulRestart_result other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSuccess()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("disableGracefulRestart_result(");
+ boolean first = true;
+
+ sb.append("success:");
+ sb.append(this.success);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class disableGracefulRestart_resultStandardSchemeFactory implements SchemeFactory {
+ public disableGracefulRestart_resultStandardScheme getScheme() {
+ return new disableGracefulRestart_resultStandardScheme();
+ }
+ }
+
+ private static class disableGracefulRestart_resultStandardScheme extends StandardScheme<disableGracefulRestart_result> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, disableGracefulRestart_result struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 0: // SUCCESS
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, disableGracefulRestart_result struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.isSetSuccess()) {
+ oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+ oprot.writeI32(struct.success);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class disableGracefulRestart_resultTupleSchemeFactory implements SchemeFactory {
+ public disableGracefulRestart_resultTupleScheme getScheme() {
+ return new disableGracefulRestart_resultTupleScheme();
+ }
+ }
+
+ private static class disableGracefulRestart_resultTupleScheme extends TupleScheme<disableGracefulRestart_result> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, disableGracefulRestart_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetSuccess()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetSuccess()) {
+ oprot.writeI32(struct.success);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, disableGracefulRestart_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.success = iprot.readI32();
+ struct.setSuccessIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class getRoutes_args implements org.apache.thrift.TBase<getRoutes_args, getRoutes_args._Fields>, java.io.Serializable, Cloneable, Comparable<getRoutes_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getRoutes_args");
+
+ private static final org.apache.thrift.protocol.TField OPTYPE_FIELD_DESC = new org.apache.thrift.protocol.TField("optype", org.apache.thrift.protocol.TType.I32, (short)1);
+ private static final org.apache.thrift.protocol.TField WIN_SIZE_FIELD_DESC = new org.apache.thrift.protocol.TField("winSize", org.apache.thrift.protocol.TType.I32, (short)2);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new getRoutes_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new getRoutes_argsTupleSchemeFactory());
+ }
+
+ public int optype; // required
+ public int winSize; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ OPTYPE((short)1, "optype"),
+ WIN_SIZE((short)2, "winSize");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // OPTYPE
+ return OPTYPE;
+ case 2: // WIN_SIZE
+ return WIN_SIZE;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __OPTYPE_ISSET_ID = 0;
+ private static final int __WINSIZE_ISSET_ID = 1;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.OPTYPE, new org.apache.thrift.meta_data.FieldMetaData("optype", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ tmpMap.put(_Fields.WIN_SIZE, new org.apache.thrift.meta_data.FieldMetaData("winSize", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getRoutes_args.class, metaDataMap);
+ }
+
+ public getRoutes_args() {
+ }
+
+ public getRoutes_args(
+ int optype,
+ int winSize)
+ {
+ this();
+ this.optype = optype;
+ setOptypeIsSet(true);
+ this.winSize = winSize;
+ setWinSizeIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public getRoutes_args(getRoutes_args other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.optype = other.optype;
+ this.winSize = other.winSize;
+ }
+
+ public getRoutes_args deepCopy() {
+ return new getRoutes_args(this);
+ }
+
+ @Override
+ public void clear() {
+ setOptypeIsSet(false);
+ this.optype = 0;
+ setWinSizeIsSet(false);
+ this.winSize = 0;
+ }
+
+ public int getOptype() {
+ return this.optype;
+ }
+
+ public getRoutes_args setOptype(int optype) {
+ this.optype = optype;
+ setOptypeIsSet(true);
+ return this;
+ }
+
+ public void unsetOptype() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __OPTYPE_ISSET_ID);
+ }
+
+ /** Returns true if field optype is set (has been assigned a value) and false otherwise */
+ public boolean isSetOptype() {
+ return EncodingUtils.testBit(__isset_bitfield, __OPTYPE_ISSET_ID);
+ }
+
+ public void setOptypeIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __OPTYPE_ISSET_ID, value);
+ }
+
+ public int getWinSize() {
+ return this.winSize;
+ }
+
+ public getRoutes_args setWinSize(int winSize) {
+ this.winSize = winSize;
+ setWinSizeIsSet(true);
+ return this;
+ }
+
+ public void unsetWinSize() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __WINSIZE_ISSET_ID);
+ }
+
+ /** Returns true if field winSize is set (has been assigned a value) and false otherwise */
+ public boolean isSetWinSize() {
+ return EncodingUtils.testBit(__isset_bitfield, __WINSIZE_ISSET_ID);
+ }
+
+ public void setWinSizeIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __WINSIZE_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case OPTYPE:
+ if (value == null) {
+ unsetOptype();
+ } else {
+ setOptype((Integer)value);
+ }
+ break;
+
+ case WIN_SIZE:
+ if (value == null) {
+ unsetWinSize();
+ } else {
+ setWinSize((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case OPTYPE:
+ return Integer.valueOf(getOptype());
+
+ case WIN_SIZE:
+ return Integer.valueOf(getWinSize());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case OPTYPE:
+ return isSetOptype();
+ case WIN_SIZE:
+ return isSetWinSize();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof getRoutes_args)
+ return this.equals((getRoutes_args)that);
+ return false;
+ }
+
+ public boolean equals(getRoutes_args that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_optype = true;
+ boolean that_present_optype = true;
+ if (this_present_optype || that_present_optype) {
+ if (!(this_present_optype && that_present_optype))
+ return false;
+ if (this.optype != that.optype)
+ return false;
+ }
+
+ boolean this_present_winSize = true;
+ boolean that_present_winSize = true;
+ if (this_present_winSize || that_present_winSize) {
+ if (!(this_present_winSize && that_present_winSize))
+ return false;
+ if (this.winSize != that.winSize)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(getRoutes_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetOptype()).compareTo(other.isSetOptype());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetOptype()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.optype, other.optype);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetWinSize()).compareTo(other.isSetWinSize());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetWinSize()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.winSize, other.winSize);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("getRoutes_args(");
+ boolean first = true;
+
+ sb.append("optype:");
+ sb.append(this.optype);
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("winSize:");
+ sb.append(this.winSize);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class getRoutes_argsStandardSchemeFactory implements SchemeFactory {
+ public getRoutes_argsStandardScheme getScheme() {
+ return new getRoutes_argsStandardScheme();
+ }
+ }
+
+ private static class getRoutes_argsStandardScheme extends StandardScheme<getRoutes_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, getRoutes_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // OPTYPE
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.optype = iprot.readI32();
+ struct.setOptypeIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 2: // WIN_SIZE
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.winSize = iprot.readI32();
+ struct.setWinSizeIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, getRoutes_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ oprot.writeFieldBegin(OPTYPE_FIELD_DESC);
+ oprot.writeI32(struct.optype);
+ oprot.writeFieldEnd();
+ oprot.writeFieldBegin(WIN_SIZE_FIELD_DESC);
+ oprot.writeI32(struct.winSize);
+ oprot.writeFieldEnd();
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class getRoutes_argsTupleSchemeFactory implements SchemeFactory {
+ public getRoutes_argsTupleScheme getScheme() {
+ return new getRoutes_argsTupleScheme();
+ }
+ }
+
+ private static class getRoutes_argsTupleScheme extends TupleScheme<getRoutes_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, getRoutes_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetOptype()) {
+ optionals.set(0);
+ }
+ if (struct.isSetWinSize()) {
+ optionals.set(1);
+ }
+ oprot.writeBitSet(optionals, 2);
+ if (struct.isSetOptype()) {
+ oprot.writeI32(struct.optype);
+ }
+ if (struct.isSetWinSize()) {
+ oprot.writeI32(struct.winSize);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, getRoutes_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(2);
+ if (incoming.get(0)) {
+ struct.optype = iprot.readI32();
+ struct.setOptypeIsSet(true);
+ }
+ if (incoming.get(1)) {
+ struct.winSize = iprot.readI32();
+ struct.setWinSizeIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class getRoutes_result implements org.apache.thrift.TBase<getRoutes_result, getRoutes_result._Fields>, java.io.Serializable, Cloneable, Comparable<getRoutes_result> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("getRoutes_result");
+
+ private static final org.apache.thrift.protocol.TField SUCCESS_FIELD_DESC = new org.apache.thrift.protocol.TField("success", org.apache.thrift.protocol.TType.STRUCT, (short)0);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new getRoutes_resultStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new getRoutes_resultTupleSchemeFactory());
+ }
+
+ public Routes success; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ SUCCESS((short)0, "success");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 0: // SUCCESS
+ return SUCCESS;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.SUCCESS, new org.apache.thrift.meta_data.FieldMetaData("success", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, Routes.class)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(getRoutes_result.class, metaDataMap);
+ }
+
+ public getRoutes_result() {
+ }
+
+ public getRoutes_result(
+ Routes success)
+ {
+ this();
+ this.success = success;
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public getRoutes_result(getRoutes_result other) {
+ if (other.isSetSuccess()) {
+ this.success = new Routes(other.success);
+ }
+ }
+
+ public getRoutes_result deepCopy() {
+ return new getRoutes_result(this);
+ }
+
+ @Override
+ public void clear() {
+ this.success = null;
+ }
+
+ public Routes getSuccess() {
+ return this.success;
+ }
+
+ public getRoutes_result setSuccess(Routes success) {
+ this.success = success;
+ return this;
+ }
+
+ public void unsetSuccess() {
+ this.success = null;
+ }
+
+ /** Returns true if field success is set (has been assigned a value) and false otherwise */
+ public boolean isSetSuccess() {
+ return this.success != null;
+ }
+
+ public void setSuccessIsSet(boolean value) {
+ if (!value) {
+ this.success = null;
+ }
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case SUCCESS:
+ if (value == null) {
+ unsetSuccess();
+ } else {
+ setSuccess((Routes)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case SUCCESS:
+ return getSuccess();
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case SUCCESS:
+ return isSetSuccess();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof getRoutes_result)
+ return this.equals((getRoutes_result)that);
+ return false;
+ }
+
+ public boolean equals(getRoutes_result that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_success = true && this.isSetSuccess();
+ boolean that_present_success = true && that.isSetSuccess();
+ if (this_present_success || that_present_success) {
+ if (!(this_present_success && that_present_success))
+ return false;
+ if (!this.success.equals(that.success))
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(getRoutes_result other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetSuccess()).compareTo(other.isSetSuccess());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetSuccess()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.success, other.success);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("getRoutes_result(");
+ boolean first = true;
+
+ sb.append("success:");
+ if (this.success == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.success);
+ }
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ if (success != null) {
+ success.validate();
+ }
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class getRoutes_resultStandardSchemeFactory implements SchemeFactory {
+ public getRoutes_resultStandardScheme getScheme() {
+ return new getRoutes_resultStandardScheme();
+ }
+ }
+
+ private static class getRoutes_resultStandardScheme extends StandardScheme<getRoutes_result> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, getRoutes_result struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 0: // SUCCESS
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRUCT) {
+ struct.success = new Routes();
+ struct.success.read(iprot);
+ struct.setSuccessIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, getRoutes_result struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.success != null) {
+ oprot.writeFieldBegin(SUCCESS_FIELD_DESC);
+ struct.success.write(oprot);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class getRoutes_resultTupleSchemeFactory implements SchemeFactory {
+ public getRoutes_resultTupleScheme getScheme() {
+ return new getRoutes_resultTupleScheme();
+ }
+ }
+
+ private static class getRoutes_resultTupleScheme extends TupleScheme<getRoutes_result> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, getRoutes_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetSuccess()) {
+ optionals.set(0);
+ }
+ oprot.writeBitSet(optionals, 1);
+ if (struct.isSetSuccess()) {
+ struct.success.write(oprot);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, getRoutes_result struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(1);
+ if (incoming.get(0)) {
+ struct.success = new Routes();
+ struct.success.read(iprot);
+ struct.setSuccessIsSet(true);
+ }
+ }
+ }
+
+ }
+
+}
--- /dev/null
+/**
+ * Autogenerated by Thrift Compiler (0.9.1)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ * @generated
+ */
+
+package org.opendaylight.bgpmanager.thrift.gen;
+
+import org.apache.thrift.scheme.IScheme;
+import org.apache.thrift.scheme.SchemeFactory;
+import org.apache.thrift.scheme.StandardScheme;
+
+import org.apache.thrift.scheme.TupleScheme;
+import org.apache.thrift.protocol.TTupleProtocol;
+import org.apache.thrift.protocol.TProtocolException;
+import org.apache.thrift.EncodingUtils;
+import org.apache.thrift.TException;
+import org.apache.thrift.async.AsyncMethodCallback;
+import org.apache.thrift.server.AbstractNonblockingServer.*;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.EnumMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.EnumSet;
+import java.util.Collections;
+import java.util.BitSet;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BgpUpdater {
+
+ public interface Iface {
+
+ public void onUpdatePushRoute(String rd, String prefix, int prefixlen, String nexthop, int label) throws org.apache.thrift.TException;
+
+ public void onUpdateWithdrawRoute(String rd, String prefix, int prefixlen) throws org.apache.thrift.TException;
+
+ public void onStartConfigResyncNotification() throws org.apache.thrift.TException;
+
+ public void onNotificationSendEvent(String prefix, byte errCode, byte errSubcode) throws org.apache.thrift.TException;
+
+ }
+
+ public interface AsyncIface {
+
+ public void onUpdatePushRoute(String rd, String prefix, int prefixlen, String nexthop, int label, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ public void onUpdateWithdrawRoute(String rd, String prefix, int prefixlen, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ public void onStartConfigResyncNotification(org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ public void onNotificationSendEvent(String prefix, byte errCode, byte errSubcode, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException;
+
+ }
+
+ public static class Client extends org.apache.thrift.TServiceClient implements Iface {
+ public static class Factory implements org.apache.thrift.TServiceClientFactory<Client> {
+ public Factory() {}
+ public Client getClient(org.apache.thrift.protocol.TProtocol prot) {
+ return new Client(prot);
+ }
+ public Client getClient(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
+ return new Client(iprot, oprot);
+ }
+ }
+
+ public Client(org.apache.thrift.protocol.TProtocol prot)
+ {
+ super(prot, prot);
+ }
+
+ public Client(org.apache.thrift.protocol.TProtocol iprot, org.apache.thrift.protocol.TProtocol oprot) {
+ super(iprot, oprot);
+ }
+
+ public void onUpdatePushRoute(String rd, String prefix, int prefixlen, String nexthop, int label) throws org.apache.thrift.TException
+ {
+ send_onUpdatePushRoute(rd, prefix, prefixlen, nexthop, label);
+ }
+
+ public void send_onUpdatePushRoute(String rd, String prefix, int prefixlen, String nexthop, int label) throws org.apache.thrift.TException
+ {
+ onUpdatePushRoute_args args = new onUpdatePushRoute_args();
+ args.setRd(rd);
+ args.setPrefix(prefix);
+ args.setPrefixlen(prefixlen);
+ args.setNexthop(nexthop);
+ args.setLabel(label);
+ sendBase("onUpdatePushRoute", args);
+ }
+
+ public void onUpdateWithdrawRoute(String rd, String prefix, int prefixlen) throws org.apache.thrift.TException
+ {
+ send_onUpdateWithdrawRoute(rd, prefix, prefixlen);
+ }
+
+ public void send_onUpdateWithdrawRoute(String rd, String prefix, int prefixlen) throws org.apache.thrift.TException
+ {
+ onUpdateWithdrawRoute_args args = new onUpdateWithdrawRoute_args();
+ args.setRd(rd);
+ args.setPrefix(prefix);
+ args.setPrefixlen(prefixlen);
+ sendBase("onUpdateWithdrawRoute", args);
+ }
+
+ public void onStartConfigResyncNotification() throws org.apache.thrift.TException
+ {
+ send_onStartConfigResyncNotification();
+ }
+
+ public void send_onStartConfigResyncNotification() throws org.apache.thrift.TException
+ {
+ onStartConfigResyncNotification_args args = new onStartConfigResyncNotification_args();
+ sendBase("onStartConfigResyncNotification", args);
+ }
+
+ public void onNotificationSendEvent(String prefix, byte errCode, byte errSubcode) throws org.apache.thrift.TException
+ {
+ send_onNotificationSendEvent(prefix, errCode, errSubcode);
+ }
+
+ public void send_onNotificationSendEvent(String prefix, byte errCode, byte errSubcode) throws org.apache.thrift.TException
+ {
+ onNotificationSendEvent_args args = new onNotificationSendEvent_args();
+ args.setPrefix(prefix);
+ args.setErrCode(errCode);
+ args.setErrSubcode(errSubcode);
+ sendBase("onNotificationSendEvent", args);
+ }
+
+ }
+ public static class AsyncClient extends org.apache.thrift.async.TAsyncClient implements AsyncIface {
+ public static class Factory implements org.apache.thrift.async.TAsyncClientFactory<AsyncClient> {
+ private org.apache.thrift.async.TAsyncClientManager clientManager;
+ private org.apache.thrift.protocol.TProtocolFactory protocolFactory;
+ public Factory(org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.protocol.TProtocolFactory protocolFactory) {
+ this.clientManager = clientManager;
+ this.protocolFactory = protocolFactory;
+ }
+ public AsyncClient getAsyncClient(org.apache.thrift.transport.TNonblockingTransport transport) {
+ return new AsyncClient(protocolFactory, clientManager, transport);
+ }
+ }
+
+ public AsyncClient(org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.async.TAsyncClientManager clientManager, org.apache.thrift.transport.TNonblockingTransport transport) {
+ super(protocolFactory, clientManager, transport);
+ }
+
+ public void onUpdatePushRoute(String rd, String prefix, int prefixlen, String nexthop, int label, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ onUpdatePushRoute_call method_call = new onUpdatePushRoute_call(rd, prefix, prefixlen, nexthop, label, resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class onUpdatePushRoute_call extends org.apache.thrift.async.TAsyncMethodCall {
+ private String rd;
+ private String prefix;
+ private int prefixlen;
+ private String nexthop;
+ private int label;
+ public onUpdatePushRoute_call(String rd, String prefix, int prefixlen, String nexthop, int label, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, true);
+ this.rd = rd;
+ this.prefix = prefix;
+ this.prefixlen = prefixlen;
+ this.nexthop = nexthop;
+ this.label = label;
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("onUpdatePushRoute", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ onUpdatePushRoute_args args = new onUpdatePushRoute_args();
+ args.setRd(rd);
+ args.setPrefix(prefix);
+ args.setPrefixlen(prefixlen);
+ args.setNexthop(nexthop);
+ args.setLabel(label);
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public void getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ }
+ }
+
+ public void onUpdateWithdrawRoute(String rd, String prefix, int prefixlen, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ onUpdateWithdrawRoute_call method_call = new onUpdateWithdrawRoute_call(rd, prefix, prefixlen, resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class onUpdateWithdrawRoute_call extends org.apache.thrift.async.TAsyncMethodCall {
+ private String rd;
+ private String prefix;
+ private int prefixlen;
+ public onUpdateWithdrawRoute_call(String rd, String prefix, int prefixlen, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, true);
+ this.rd = rd;
+ this.prefix = prefix;
+ this.prefixlen = prefixlen;
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("onUpdateWithdrawRoute", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ onUpdateWithdrawRoute_args args = new onUpdateWithdrawRoute_args();
+ args.setRd(rd);
+ args.setPrefix(prefix);
+ args.setPrefixlen(prefixlen);
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public void getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ }
+ }
+
+ public void onStartConfigResyncNotification(org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ onStartConfigResyncNotification_call method_call = new onStartConfigResyncNotification_call(resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class onStartConfigResyncNotification_call extends org.apache.thrift.async.TAsyncMethodCall {
+ public onStartConfigResyncNotification_call(org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, true);
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("onStartConfigResyncNotification", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ onStartConfigResyncNotification_args args = new onStartConfigResyncNotification_args();
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public void getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ }
+ }
+
+ public void onNotificationSendEvent(String prefix, byte errCode, byte errSubcode, org.apache.thrift.async.AsyncMethodCallback resultHandler) throws org.apache.thrift.TException {
+ checkReady();
+ onNotificationSendEvent_call method_call = new onNotificationSendEvent_call(prefix, errCode, errSubcode, resultHandler, this, ___protocolFactory, ___transport);
+ this.___currentMethod = method_call;
+ ___manager.call(method_call);
+ }
+
+ public static class onNotificationSendEvent_call extends org.apache.thrift.async.TAsyncMethodCall {
+ private String prefix;
+ private byte errCode;
+ private byte errSubcode;
+ public onNotificationSendEvent_call(String prefix, byte errCode, byte errSubcode, org.apache.thrift.async.AsyncMethodCallback resultHandler, org.apache.thrift.async.TAsyncClient client, org.apache.thrift.protocol.TProtocolFactory protocolFactory, org.apache.thrift.transport.TNonblockingTransport transport) throws org.apache.thrift.TException {
+ super(client, protocolFactory, transport, resultHandler, true);
+ this.prefix = prefix;
+ this.errCode = errCode;
+ this.errSubcode = errSubcode;
+ }
+
+ public void write_args(org.apache.thrift.protocol.TProtocol prot) throws org.apache.thrift.TException {
+ prot.writeMessageBegin(new org.apache.thrift.protocol.TMessage("onNotificationSendEvent", org.apache.thrift.protocol.TMessageType.CALL, 0));
+ onNotificationSendEvent_args args = new onNotificationSendEvent_args();
+ args.setPrefix(prefix);
+ args.setErrCode(errCode);
+ args.setErrSubcode(errSubcode);
+ args.write(prot);
+ prot.writeMessageEnd();
+ }
+
+ public void getResult() throws org.apache.thrift.TException {
+ if (getState() != org.apache.thrift.async.TAsyncMethodCall.State.RESPONSE_READ) {
+ throw new IllegalStateException("Method call not finished!");
+ }
+ org.apache.thrift.transport.TMemoryInputTransport memoryTransport = new org.apache.thrift.transport.TMemoryInputTransport(getFrameBuffer().array());
+ org.apache.thrift.protocol.TProtocol prot = client.getProtocolFactory().getProtocol(memoryTransport);
+ }
+ }
+
+ }
+
+ public static class Processor<I extends Iface> extends org.apache.thrift.TBaseProcessor<I> implements org.apache.thrift.TProcessor {
+ private static final Logger LOGGER = LoggerFactory.getLogger(Processor.class.getName());
+ public Processor(I iface) {
+ super(iface, getProcessMap(new HashMap<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>>()));
+ }
+
+ protected Processor(I iface, Map<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>> processMap) {
+ super(iface, getProcessMap(processMap));
+ }
+
+ private static <I extends Iface> Map<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>> getProcessMap(Map<String, org.apache.thrift.ProcessFunction<I, ? extends org.apache.thrift.TBase>> processMap) {
+ processMap.put("onUpdatePushRoute", new onUpdatePushRoute());
+ processMap.put("onUpdateWithdrawRoute", new onUpdateWithdrawRoute());
+ processMap.put("onStartConfigResyncNotification", new onStartConfigResyncNotification());
+ processMap.put("onNotificationSendEvent", new onNotificationSendEvent());
+ return processMap;
+ }
+
+ public static class onUpdatePushRoute<I extends Iface> extends org.apache.thrift.ProcessFunction<I, onUpdatePushRoute_args> {
+ public onUpdatePushRoute() {
+ super("onUpdatePushRoute");
+ }
+
+ public onUpdatePushRoute_args getEmptyArgsInstance() {
+ return new onUpdatePushRoute_args();
+ }
+
+ protected boolean isOneway() {
+ return true;
+ }
+
+ public org.apache.thrift.TBase getResult(I iface, onUpdatePushRoute_args args) throws org.apache.thrift.TException {
+ iface.onUpdatePushRoute(args.rd, args.prefix, args.prefixlen, args.nexthop, args.label);
+ return null;
+ }
+ }
+
+ public static class onUpdateWithdrawRoute<I extends Iface> extends org.apache.thrift.ProcessFunction<I, onUpdateWithdrawRoute_args> {
+ public onUpdateWithdrawRoute() {
+ super("onUpdateWithdrawRoute");
+ }
+
+ public onUpdateWithdrawRoute_args getEmptyArgsInstance() {
+ return new onUpdateWithdrawRoute_args();
+ }
+
+ protected boolean isOneway() {
+ return true;
+ }
+
+ public org.apache.thrift.TBase getResult(I iface, onUpdateWithdrawRoute_args args) throws org.apache.thrift.TException {
+ iface.onUpdateWithdrawRoute(args.rd, args.prefix, args.prefixlen);
+ return null;
+ }
+ }
+
+ public static class onStartConfigResyncNotification<I extends Iface> extends org.apache.thrift.ProcessFunction<I, onStartConfigResyncNotification_args> {
+ public onStartConfigResyncNotification() {
+ super("onStartConfigResyncNotification");
+ }
+
+ public onStartConfigResyncNotification_args getEmptyArgsInstance() {
+ return new onStartConfigResyncNotification_args();
+ }
+
+ protected boolean isOneway() {
+ return true;
+ }
+
+ public org.apache.thrift.TBase getResult(I iface, onStartConfigResyncNotification_args args) throws org.apache.thrift.TException {
+ iface.onStartConfigResyncNotification();
+ return null;
+ }
+ }
+
+ public static class onNotificationSendEvent<I extends Iface> extends org.apache.thrift.ProcessFunction<I, onNotificationSendEvent_args> {
+ public onNotificationSendEvent() {
+ super("onNotificationSendEvent");
+ }
+
+ public onNotificationSendEvent_args getEmptyArgsInstance() {
+ return new onNotificationSendEvent_args();
+ }
+
+ protected boolean isOneway() {
+ return true;
+ }
+
+ public org.apache.thrift.TBase getResult(I iface, onNotificationSendEvent_args args) throws org.apache.thrift.TException {
+ iface.onNotificationSendEvent(args.prefix, args.errCode, args.errSubcode);
+ return null;
+ }
+ }
+
+ }
+
+ public static class AsyncProcessor<I extends AsyncIface> extends org.apache.thrift.TBaseAsyncProcessor<I> {
+ private static final Logger LOGGER = LoggerFactory.getLogger(AsyncProcessor.class.getName());
+ public AsyncProcessor(I iface) {
+ super(iface, getProcessMap(new HashMap<String, org.apache.thrift.AsyncProcessFunction<I, ? extends org.apache.thrift.TBase, ?>>()));
+ }
+
+ protected AsyncProcessor(I iface, Map<String, org.apache.thrift.AsyncProcessFunction<I, ? extends org.apache.thrift.TBase, ?>> processMap) {
+ super(iface, getProcessMap(processMap));
+ }
+
+ private static <I extends AsyncIface> Map<String, org.apache.thrift.AsyncProcessFunction<I, ? extends org.apache.thrift.TBase,?>> getProcessMap(Map<String, org.apache.thrift.AsyncProcessFunction<I, ? extends org.apache.thrift.TBase, ?>> processMap) {
+ processMap.put("onUpdatePushRoute", new onUpdatePushRoute());
+ processMap.put("onUpdateWithdrawRoute", new onUpdateWithdrawRoute());
+ processMap.put("onStartConfigResyncNotification", new onStartConfigResyncNotification());
+ processMap.put("onNotificationSendEvent", new onNotificationSendEvent());
+ return processMap;
+ }
+
+ public static class onUpdatePushRoute<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, onUpdatePushRoute_args, Void> {
+ public onUpdatePushRoute() {
+ super("onUpdatePushRoute");
+ }
+
+ public onUpdatePushRoute_args getEmptyArgsInstance() {
+ return new onUpdatePushRoute_args();
+ }
+
+ public AsyncMethodCallback<Void> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Void>() {
+ public void onComplete(Void o) {
+ }
+ public void onError(Exception e) {
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return true;
+ }
+
+ public void start(I iface, onUpdatePushRoute_args args, org.apache.thrift.async.AsyncMethodCallback<Void> resultHandler) throws TException {
+ iface.onUpdatePushRoute(args.rd, args.prefix, args.prefixlen, args.nexthop, args.label,resultHandler);
+ }
+ }
+
+ public static class onUpdateWithdrawRoute<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, onUpdateWithdrawRoute_args, Void> {
+ public onUpdateWithdrawRoute() {
+ super("onUpdateWithdrawRoute");
+ }
+
+ public onUpdateWithdrawRoute_args getEmptyArgsInstance() {
+ return new onUpdateWithdrawRoute_args();
+ }
+
+ public AsyncMethodCallback<Void> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Void>() {
+ public void onComplete(Void o) {
+ }
+ public void onError(Exception e) {
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return true;
+ }
+
+ public void start(I iface, onUpdateWithdrawRoute_args args, org.apache.thrift.async.AsyncMethodCallback<Void> resultHandler) throws TException {
+ iface.onUpdateWithdrawRoute(args.rd, args.prefix, args.prefixlen,resultHandler);
+ }
+ }
+
+ public static class onStartConfigResyncNotification<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, onStartConfigResyncNotification_args, Void> {
+ public onStartConfigResyncNotification() {
+ super("onStartConfigResyncNotification");
+ }
+
+ public onStartConfigResyncNotification_args getEmptyArgsInstance() {
+ return new onStartConfigResyncNotification_args();
+ }
+
+ public AsyncMethodCallback<Void> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Void>() {
+ public void onComplete(Void o) {
+ }
+ public void onError(Exception e) {
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return true;
+ }
+
+ public void start(I iface, onStartConfigResyncNotification_args args, org.apache.thrift.async.AsyncMethodCallback<Void> resultHandler) throws TException {
+ iface.onStartConfigResyncNotification(resultHandler);
+ }
+ }
+
+ public static class onNotificationSendEvent<I extends AsyncIface> extends org.apache.thrift.AsyncProcessFunction<I, onNotificationSendEvent_args, Void> {
+ public onNotificationSendEvent() {
+ super("onNotificationSendEvent");
+ }
+
+ public onNotificationSendEvent_args getEmptyArgsInstance() {
+ return new onNotificationSendEvent_args();
+ }
+
+ public AsyncMethodCallback<Void> getResultHandler(final AsyncFrameBuffer fb, final int seqid) {
+ final org.apache.thrift.AsyncProcessFunction fcall = this;
+ return new AsyncMethodCallback<Void>() {
+ public void onComplete(Void o) {
+ }
+ public void onError(Exception e) {
+ }
+ };
+ }
+
+ protected boolean isOneway() {
+ return true;
+ }
+
+ public void start(I iface, onNotificationSendEvent_args args, org.apache.thrift.async.AsyncMethodCallback<Void> resultHandler) throws TException {
+ iface.onNotificationSendEvent(args.prefix, args.errCode, args.errSubcode,resultHandler);
+ }
+ }
+
+ }
+
+ public static class onUpdatePushRoute_args implements org.apache.thrift.TBase<onUpdatePushRoute_args, onUpdatePushRoute_args._Fields>, java.io.Serializable, Cloneable, Comparable<onUpdatePushRoute_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("onUpdatePushRoute_args");
+
+ private static final org.apache.thrift.protocol.TField RD_FIELD_DESC = new org.apache.thrift.protocol.TField("rd", org.apache.thrift.protocol.TType.STRING, (short)1);
+ private static final org.apache.thrift.protocol.TField PREFIX_FIELD_DESC = new org.apache.thrift.protocol.TField("prefix", org.apache.thrift.protocol.TType.STRING, (short)2);
+ private static final org.apache.thrift.protocol.TField PREFIXLEN_FIELD_DESC = new org.apache.thrift.protocol.TField("prefixlen", org.apache.thrift.protocol.TType.I32, (short)3);
+ private static final org.apache.thrift.protocol.TField NEXTHOP_FIELD_DESC = new org.apache.thrift.protocol.TField("nexthop", org.apache.thrift.protocol.TType.STRING, (short)4);
+ private static final org.apache.thrift.protocol.TField LABEL_FIELD_DESC = new org.apache.thrift.protocol.TField("label", org.apache.thrift.protocol.TType.I32, (short)5);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new onUpdatePushRoute_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new onUpdatePushRoute_argsTupleSchemeFactory());
+ }
+
+ public String rd; // required
+ public String prefix; // required
+ public int prefixlen; // required
+ public String nexthop; // required
+ public int label; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ RD((short)1, "rd"),
+ PREFIX((short)2, "prefix"),
+ PREFIXLEN((short)3, "prefixlen"),
+ NEXTHOP((short)4, "nexthop"),
+ LABEL((short)5, "label");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // RD
+ return RD;
+ case 2: // PREFIX
+ return PREFIX;
+ case 3: // PREFIXLEN
+ return PREFIXLEN;
+ case 4: // NEXTHOP
+ return NEXTHOP;
+ case 5: // LABEL
+ return LABEL;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __PREFIXLEN_ISSET_ID = 0;
+ private static final int __LABEL_ISSET_ID = 1;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.RD, new org.apache.thrift.meta_data.FieldMetaData("rd", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ tmpMap.put(_Fields.PREFIX, new org.apache.thrift.meta_data.FieldMetaData("prefix", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ tmpMap.put(_Fields.PREFIXLEN, new org.apache.thrift.meta_data.FieldMetaData("prefixlen", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ tmpMap.put(_Fields.NEXTHOP, new org.apache.thrift.meta_data.FieldMetaData("nexthop", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ tmpMap.put(_Fields.LABEL, new org.apache.thrift.meta_data.FieldMetaData("label", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(onUpdatePushRoute_args.class, metaDataMap);
+ }
+
+ public onUpdatePushRoute_args() {
+ }
+
+ public onUpdatePushRoute_args(
+ String rd,
+ String prefix,
+ int prefixlen,
+ String nexthop,
+ int label)
+ {
+ this();
+ this.rd = rd;
+ this.prefix = prefix;
+ this.prefixlen = prefixlen;
+ setPrefixlenIsSet(true);
+ this.nexthop = nexthop;
+ this.label = label;
+ setLabelIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public onUpdatePushRoute_args(onUpdatePushRoute_args other) {
+ __isset_bitfield = other.__isset_bitfield;
+ if (other.isSetRd()) {
+ this.rd = other.rd;
+ }
+ if (other.isSetPrefix()) {
+ this.prefix = other.prefix;
+ }
+ this.prefixlen = other.prefixlen;
+ if (other.isSetNexthop()) {
+ this.nexthop = other.nexthop;
+ }
+ this.label = other.label;
+ }
+
+ public onUpdatePushRoute_args deepCopy() {
+ return new onUpdatePushRoute_args(this);
+ }
+
+ @Override
+ public void clear() {
+ this.rd = null;
+ this.prefix = null;
+ setPrefixlenIsSet(false);
+ this.prefixlen = 0;
+ this.nexthop = null;
+ setLabelIsSet(false);
+ this.label = 0;
+ }
+
+ public String getRd() {
+ return this.rd;
+ }
+
+ public onUpdatePushRoute_args setRd(String rd) {
+ this.rd = rd;
+ return this;
+ }
+
+ public void unsetRd() {
+ this.rd = null;
+ }
+
+ /** Returns true if field rd is set (has been assigned a value) and false otherwise */
+ public boolean isSetRd() {
+ return this.rd != null;
+ }
+
+ public void setRdIsSet(boolean value) {
+ if (!value) {
+ this.rd = null;
+ }
+ }
+
+ public String getPrefix() {
+ return this.prefix;
+ }
+
+ public onUpdatePushRoute_args setPrefix(String prefix) {
+ this.prefix = prefix;
+ return this;
+ }
+
+ public void unsetPrefix() {
+ this.prefix = null;
+ }
+
+ /** Returns true if field prefix is set (has been assigned a value) and false otherwise */
+ public boolean isSetPrefix() {
+ return this.prefix != null;
+ }
+
+ public void setPrefixIsSet(boolean value) {
+ if (!value) {
+ this.prefix = null;
+ }
+ }
+
+ public int getPrefixlen() {
+ return this.prefixlen;
+ }
+
+ public onUpdatePushRoute_args setPrefixlen(int prefixlen) {
+ this.prefixlen = prefixlen;
+ setPrefixlenIsSet(true);
+ return this;
+ }
+
+ public void unsetPrefixlen() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __PREFIXLEN_ISSET_ID);
+ }
+
+ /** Returns true if field prefixlen is set (has been assigned a value) and false otherwise */
+ public boolean isSetPrefixlen() {
+ return EncodingUtils.testBit(__isset_bitfield, __PREFIXLEN_ISSET_ID);
+ }
+
+ public void setPrefixlenIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __PREFIXLEN_ISSET_ID, value);
+ }
+
+ public String getNexthop() {
+ return this.nexthop;
+ }
+
+ public onUpdatePushRoute_args setNexthop(String nexthop) {
+ this.nexthop = nexthop;
+ return this;
+ }
+
+ public void unsetNexthop() {
+ this.nexthop = null;
+ }
+
+ /** Returns true if field nexthop is set (has been assigned a value) and false otherwise */
+ public boolean isSetNexthop() {
+ return this.nexthop != null;
+ }
+
+ public void setNexthopIsSet(boolean value) {
+ if (!value) {
+ this.nexthop = null;
+ }
+ }
+
+ public int getLabel() {
+ return this.label;
+ }
+
+ public onUpdatePushRoute_args setLabel(int label) {
+ this.label = label;
+ setLabelIsSet(true);
+ return this;
+ }
+
+ public void unsetLabel() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __LABEL_ISSET_ID);
+ }
+
+ /** Returns true if field label is set (has been assigned a value) and false otherwise */
+ public boolean isSetLabel() {
+ return EncodingUtils.testBit(__isset_bitfield, __LABEL_ISSET_ID);
+ }
+
+ public void setLabelIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __LABEL_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case RD:
+ if (value == null) {
+ unsetRd();
+ } else {
+ setRd((String)value);
+ }
+ break;
+
+ case PREFIX:
+ if (value == null) {
+ unsetPrefix();
+ } else {
+ setPrefix((String)value);
+ }
+ break;
+
+ case PREFIXLEN:
+ if (value == null) {
+ unsetPrefixlen();
+ } else {
+ setPrefixlen((Integer)value);
+ }
+ break;
+
+ case NEXTHOP:
+ if (value == null) {
+ unsetNexthop();
+ } else {
+ setNexthop((String)value);
+ }
+ break;
+
+ case LABEL:
+ if (value == null) {
+ unsetLabel();
+ } else {
+ setLabel((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case RD:
+ return getRd();
+
+ case PREFIX:
+ return getPrefix();
+
+ case PREFIXLEN:
+ return Integer.valueOf(getPrefixlen());
+
+ case NEXTHOP:
+ return getNexthop();
+
+ case LABEL:
+ return Integer.valueOf(getLabel());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case RD:
+ return isSetRd();
+ case PREFIX:
+ return isSetPrefix();
+ case PREFIXLEN:
+ return isSetPrefixlen();
+ case NEXTHOP:
+ return isSetNexthop();
+ case LABEL:
+ return isSetLabel();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof onUpdatePushRoute_args)
+ return this.equals((onUpdatePushRoute_args)that);
+ return false;
+ }
+
+ public boolean equals(onUpdatePushRoute_args that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_rd = true && this.isSetRd();
+ boolean that_present_rd = true && that.isSetRd();
+ if (this_present_rd || that_present_rd) {
+ if (!(this_present_rd && that_present_rd))
+ return false;
+ if (!this.rd.equals(that.rd))
+ return false;
+ }
+
+ boolean this_present_prefix = true && this.isSetPrefix();
+ boolean that_present_prefix = true && that.isSetPrefix();
+ if (this_present_prefix || that_present_prefix) {
+ if (!(this_present_prefix && that_present_prefix))
+ return false;
+ if (!this.prefix.equals(that.prefix))
+ return false;
+ }
+
+ boolean this_present_prefixlen = true;
+ boolean that_present_prefixlen = true;
+ if (this_present_prefixlen || that_present_prefixlen) {
+ if (!(this_present_prefixlen && that_present_prefixlen))
+ return false;
+ if (this.prefixlen != that.prefixlen)
+ return false;
+ }
+
+ boolean this_present_nexthop = true && this.isSetNexthop();
+ boolean that_present_nexthop = true && that.isSetNexthop();
+ if (this_present_nexthop || that_present_nexthop) {
+ if (!(this_present_nexthop && that_present_nexthop))
+ return false;
+ if (!this.nexthop.equals(that.nexthop))
+ return false;
+ }
+
+ boolean this_present_label = true;
+ boolean that_present_label = true;
+ if (this_present_label || that_present_label) {
+ if (!(this_present_label && that_present_label))
+ return false;
+ if (this.label != that.label)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(onUpdatePushRoute_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetRd()).compareTo(other.isSetRd());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetRd()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.rd, other.rd);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetPrefix()).compareTo(other.isSetPrefix());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetPrefix()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.prefix, other.prefix);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetPrefixlen()).compareTo(other.isSetPrefixlen());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetPrefixlen()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.prefixlen, other.prefixlen);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetNexthop()).compareTo(other.isSetNexthop());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetNexthop()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.nexthop, other.nexthop);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetLabel()).compareTo(other.isSetLabel());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetLabel()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.label, other.label);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("onUpdatePushRoute_args(");
+ boolean first = true;
+
+ sb.append("rd:");
+ if (this.rd == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.rd);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("prefix:");
+ if (this.prefix == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.prefix);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("prefixlen:");
+ sb.append(this.prefixlen);
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("nexthop:");
+ if (this.nexthop == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.nexthop);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("label:");
+ sb.append(this.label);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class onUpdatePushRoute_argsStandardSchemeFactory implements SchemeFactory {
+ public onUpdatePushRoute_argsStandardScheme getScheme() {
+ return new onUpdatePushRoute_argsStandardScheme();
+ }
+ }
+
+ private static class onUpdatePushRoute_argsStandardScheme extends StandardScheme<onUpdatePushRoute_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, onUpdatePushRoute_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // RD
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.rd = iprot.readString();
+ struct.setRdIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 2: // PREFIX
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.prefix = iprot.readString();
+ struct.setPrefixIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 3: // PREFIXLEN
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.prefixlen = iprot.readI32();
+ struct.setPrefixlenIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 4: // NEXTHOP
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.nexthop = iprot.readString();
+ struct.setNexthopIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 5: // LABEL
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.label = iprot.readI32();
+ struct.setLabelIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, onUpdatePushRoute_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.rd != null) {
+ oprot.writeFieldBegin(RD_FIELD_DESC);
+ oprot.writeString(struct.rd);
+ oprot.writeFieldEnd();
+ }
+ if (struct.prefix != null) {
+ oprot.writeFieldBegin(PREFIX_FIELD_DESC);
+ oprot.writeString(struct.prefix);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldBegin(PREFIXLEN_FIELD_DESC);
+ oprot.writeI32(struct.prefixlen);
+ oprot.writeFieldEnd();
+ if (struct.nexthop != null) {
+ oprot.writeFieldBegin(NEXTHOP_FIELD_DESC);
+ oprot.writeString(struct.nexthop);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldBegin(LABEL_FIELD_DESC);
+ oprot.writeI32(struct.label);
+ oprot.writeFieldEnd();
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class onUpdatePushRoute_argsTupleSchemeFactory implements SchemeFactory {
+ public onUpdatePushRoute_argsTupleScheme getScheme() {
+ return new onUpdatePushRoute_argsTupleScheme();
+ }
+ }
+
+ private static class onUpdatePushRoute_argsTupleScheme extends TupleScheme<onUpdatePushRoute_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, onUpdatePushRoute_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetRd()) {
+ optionals.set(0);
+ }
+ if (struct.isSetPrefix()) {
+ optionals.set(1);
+ }
+ if (struct.isSetPrefixlen()) {
+ optionals.set(2);
+ }
+ if (struct.isSetNexthop()) {
+ optionals.set(3);
+ }
+ if (struct.isSetLabel()) {
+ optionals.set(4);
+ }
+ oprot.writeBitSet(optionals, 5);
+ if (struct.isSetRd()) {
+ oprot.writeString(struct.rd);
+ }
+ if (struct.isSetPrefix()) {
+ oprot.writeString(struct.prefix);
+ }
+ if (struct.isSetPrefixlen()) {
+ oprot.writeI32(struct.prefixlen);
+ }
+ if (struct.isSetNexthop()) {
+ oprot.writeString(struct.nexthop);
+ }
+ if (struct.isSetLabel()) {
+ oprot.writeI32(struct.label);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, onUpdatePushRoute_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(5);
+ if (incoming.get(0)) {
+ struct.rd = iprot.readString();
+ struct.setRdIsSet(true);
+ }
+ if (incoming.get(1)) {
+ struct.prefix = iprot.readString();
+ struct.setPrefixIsSet(true);
+ }
+ if (incoming.get(2)) {
+ struct.prefixlen = iprot.readI32();
+ struct.setPrefixlenIsSet(true);
+ }
+ if (incoming.get(3)) {
+ struct.nexthop = iprot.readString();
+ struct.setNexthopIsSet(true);
+ }
+ if (incoming.get(4)) {
+ struct.label = iprot.readI32();
+ struct.setLabelIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class onUpdateWithdrawRoute_args implements org.apache.thrift.TBase<onUpdateWithdrawRoute_args, onUpdateWithdrawRoute_args._Fields>, java.io.Serializable, Cloneable, Comparable<onUpdateWithdrawRoute_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("onUpdateWithdrawRoute_args");
+
+ private static final org.apache.thrift.protocol.TField RD_FIELD_DESC = new org.apache.thrift.protocol.TField("rd", org.apache.thrift.protocol.TType.STRING, (short)1);
+ private static final org.apache.thrift.protocol.TField PREFIX_FIELD_DESC = new org.apache.thrift.protocol.TField("prefix", org.apache.thrift.protocol.TType.STRING, (short)2);
+ private static final org.apache.thrift.protocol.TField PREFIXLEN_FIELD_DESC = new org.apache.thrift.protocol.TField("prefixlen", org.apache.thrift.protocol.TType.I32, (short)3);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new onUpdateWithdrawRoute_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new onUpdateWithdrawRoute_argsTupleSchemeFactory());
+ }
+
+ public String rd; // required
+ public String prefix; // required
+ public int prefixlen; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ RD((short)1, "rd"),
+ PREFIX((short)2, "prefix"),
+ PREFIXLEN((short)3, "prefixlen");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // RD
+ return RD;
+ case 2: // PREFIX
+ return PREFIX;
+ case 3: // PREFIXLEN
+ return PREFIXLEN;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __PREFIXLEN_ISSET_ID = 0;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.RD, new org.apache.thrift.meta_data.FieldMetaData("rd", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ tmpMap.put(_Fields.PREFIX, new org.apache.thrift.meta_data.FieldMetaData("prefix", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ tmpMap.put(_Fields.PREFIXLEN, new org.apache.thrift.meta_data.FieldMetaData("prefixlen", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(onUpdateWithdrawRoute_args.class, metaDataMap);
+ }
+
+ public onUpdateWithdrawRoute_args() {
+ }
+
+ public onUpdateWithdrawRoute_args(
+ String rd,
+ String prefix,
+ int prefixlen)
+ {
+ this();
+ this.rd = rd;
+ this.prefix = prefix;
+ this.prefixlen = prefixlen;
+ setPrefixlenIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public onUpdateWithdrawRoute_args(onUpdateWithdrawRoute_args other) {
+ __isset_bitfield = other.__isset_bitfield;
+ if (other.isSetRd()) {
+ this.rd = other.rd;
+ }
+ if (other.isSetPrefix()) {
+ this.prefix = other.prefix;
+ }
+ this.prefixlen = other.prefixlen;
+ }
+
+ public onUpdateWithdrawRoute_args deepCopy() {
+ return new onUpdateWithdrawRoute_args(this);
+ }
+
+ @Override
+ public void clear() {
+ this.rd = null;
+ this.prefix = null;
+ setPrefixlenIsSet(false);
+ this.prefixlen = 0;
+ }
+
+ public String getRd() {
+ return this.rd;
+ }
+
+ public onUpdateWithdrawRoute_args setRd(String rd) {
+ this.rd = rd;
+ return this;
+ }
+
+ public void unsetRd() {
+ this.rd = null;
+ }
+
+ /** Returns true if field rd is set (has been assigned a value) and false otherwise */
+ public boolean isSetRd() {
+ return this.rd != null;
+ }
+
+ public void setRdIsSet(boolean value) {
+ if (!value) {
+ this.rd = null;
+ }
+ }
+
+ public String getPrefix() {
+ return this.prefix;
+ }
+
+ public onUpdateWithdrawRoute_args setPrefix(String prefix) {
+ this.prefix = prefix;
+ return this;
+ }
+
+ public void unsetPrefix() {
+ this.prefix = null;
+ }
+
+ /** Returns true if field prefix is set (has been assigned a value) and false otherwise */
+ public boolean isSetPrefix() {
+ return this.prefix != null;
+ }
+
+ public void setPrefixIsSet(boolean value) {
+ if (!value) {
+ this.prefix = null;
+ }
+ }
+
+ public int getPrefixlen() {
+ return this.prefixlen;
+ }
+
+ public onUpdateWithdrawRoute_args setPrefixlen(int prefixlen) {
+ this.prefixlen = prefixlen;
+ setPrefixlenIsSet(true);
+ return this;
+ }
+
+ public void unsetPrefixlen() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __PREFIXLEN_ISSET_ID);
+ }
+
+ /** Returns true if field prefixlen is set (has been assigned a value) and false otherwise */
+ public boolean isSetPrefixlen() {
+ return EncodingUtils.testBit(__isset_bitfield, __PREFIXLEN_ISSET_ID);
+ }
+
+ public void setPrefixlenIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __PREFIXLEN_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case RD:
+ if (value == null) {
+ unsetRd();
+ } else {
+ setRd((String)value);
+ }
+ break;
+
+ case PREFIX:
+ if (value == null) {
+ unsetPrefix();
+ } else {
+ setPrefix((String)value);
+ }
+ break;
+
+ case PREFIXLEN:
+ if (value == null) {
+ unsetPrefixlen();
+ } else {
+ setPrefixlen((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case RD:
+ return getRd();
+
+ case PREFIX:
+ return getPrefix();
+
+ case PREFIXLEN:
+ return Integer.valueOf(getPrefixlen());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case RD:
+ return isSetRd();
+ case PREFIX:
+ return isSetPrefix();
+ case PREFIXLEN:
+ return isSetPrefixlen();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof onUpdateWithdrawRoute_args)
+ return this.equals((onUpdateWithdrawRoute_args)that);
+ return false;
+ }
+
+ public boolean equals(onUpdateWithdrawRoute_args that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_rd = true && this.isSetRd();
+ boolean that_present_rd = true && that.isSetRd();
+ if (this_present_rd || that_present_rd) {
+ if (!(this_present_rd && that_present_rd))
+ return false;
+ if (!this.rd.equals(that.rd))
+ return false;
+ }
+
+ boolean this_present_prefix = true && this.isSetPrefix();
+ boolean that_present_prefix = true && that.isSetPrefix();
+ if (this_present_prefix || that_present_prefix) {
+ if (!(this_present_prefix && that_present_prefix))
+ return false;
+ if (!this.prefix.equals(that.prefix))
+ return false;
+ }
+
+ boolean this_present_prefixlen = true;
+ boolean that_present_prefixlen = true;
+ if (this_present_prefixlen || that_present_prefixlen) {
+ if (!(this_present_prefixlen && that_present_prefixlen))
+ return false;
+ if (this.prefixlen != that.prefixlen)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(onUpdateWithdrawRoute_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetRd()).compareTo(other.isSetRd());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetRd()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.rd, other.rd);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetPrefix()).compareTo(other.isSetPrefix());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetPrefix()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.prefix, other.prefix);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetPrefixlen()).compareTo(other.isSetPrefixlen());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetPrefixlen()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.prefixlen, other.prefixlen);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("onUpdateWithdrawRoute_args(");
+ boolean first = true;
+
+ sb.append("rd:");
+ if (this.rd == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.rd);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("prefix:");
+ if (this.prefix == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.prefix);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("prefixlen:");
+ sb.append(this.prefixlen);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class onUpdateWithdrawRoute_argsStandardSchemeFactory implements SchemeFactory {
+ public onUpdateWithdrawRoute_argsStandardScheme getScheme() {
+ return new onUpdateWithdrawRoute_argsStandardScheme();
+ }
+ }
+
+ private static class onUpdateWithdrawRoute_argsStandardScheme extends StandardScheme<onUpdateWithdrawRoute_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, onUpdateWithdrawRoute_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // RD
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.rd = iprot.readString();
+ struct.setRdIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 2: // PREFIX
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.prefix = iprot.readString();
+ struct.setPrefixIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 3: // PREFIXLEN
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.prefixlen = iprot.readI32();
+ struct.setPrefixlenIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, onUpdateWithdrawRoute_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.rd != null) {
+ oprot.writeFieldBegin(RD_FIELD_DESC);
+ oprot.writeString(struct.rd);
+ oprot.writeFieldEnd();
+ }
+ if (struct.prefix != null) {
+ oprot.writeFieldBegin(PREFIX_FIELD_DESC);
+ oprot.writeString(struct.prefix);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldBegin(PREFIXLEN_FIELD_DESC);
+ oprot.writeI32(struct.prefixlen);
+ oprot.writeFieldEnd();
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class onUpdateWithdrawRoute_argsTupleSchemeFactory implements SchemeFactory {
+ public onUpdateWithdrawRoute_argsTupleScheme getScheme() {
+ return new onUpdateWithdrawRoute_argsTupleScheme();
+ }
+ }
+
+ private static class onUpdateWithdrawRoute_argsTupleScheme extends TupleScheme<onUpdateWithdrawRoute_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, onUpdateWithdrawRoute_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetRd()) {
+ optionals.set(0);
+ }
+ if (struct.isSetPrefix()) {
+ optionals.set(1);
+ }
+ if (struct.isSetPrefixlen()) {
+ optionals.set(2);
+ }
+ oprot.writeBitSet(optionals, 3);
+ if (struct.isSetRd()) {
+ oprot.writeString(struct.rd);
+ }
+ if (struct.isSetPrefix()) {
+ oprot.writeString(struct.prefix);
+ }
+ if (struct.isSetPrefixlen()) {
+ oprot.writeI32(struct.prefixlen);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, onUpdateWithdrawRoute_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(3);
+ if (incoming.get(0)) {
+ struct.rd = iprot.readString();
+ struct.setRdIsSet(true);
+ }
+ if (incoming.get(1)) {
+ struct.prefix = iprot.readString();
+ struct.setPrefixIsSet(true);
+ }
+ if (incoming.get(2)) {
+ struct.prefixlen = iprot.readI32();
+ struct.setPrefixlenIsSet(true);
+ }
+ }
+ }
+
+ }
+
+ public static class onStartConfigResyncNotification_args implements org.apache.thrift.TBase<onStartConfigResyncNotification_args, onStartConfigResyncNotification_args._Fields>, java.io.Serializable, Cloneable, Comparable<onStartConfigResyncNotification_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("onStartConfigResyncNotification_args");
+
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new onStartConfigResyncNotification_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new onStartConfigResyncNotification_argsTupleSchemeFactory());
+ }
+
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+;
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(onStartConfigResyncNotification_args.class, metaDataMap);
+ }
+
+ public onStartConfigResyncNotification_args() {
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public onStartConfigResyncNotification_args(onStartConfigResyncNotification_args other) {
+ }
+
+ public onStartConfigResyncNotification_args deepCopy() {
+ return new onStartConfigResyncNotification_args(this);
+ }
+
+ @Override
+ public void clear() {
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof onStartConfigResyncNotification_args)
+ return this.equals((onStartConfigResyncNotification_args)that);
+ return false;
+ }
+
+ public boolean equals(onStartConfigResyncNotification_args that) {
+ if (that == null)
+ return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(onStartConfigResyncNotification_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("onStartConfigResyncNotification_args(");
+ boolean first = true;
+
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class onStartConfigResyncNotification_argsStandardSchemeFactory implements SchemeFactory {
+ public onStartConfigResyncNotification_argsStandardScheme getScheme() {
+ return new onStartConfigResyncNotification_argsStandardScheme();
+ }
+ }
+
+ private static class onStartConfigResyncNotification_argsStandardScheme extends StandardScheme<onStartConfigResyncNotification_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, onStartConfigResyncNotification_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, onStartConfigResyncNotification_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class onStartConfigResyncNotification_argsTupleSchemeFactory implements SchemeFactory {
+ public onStartConfigResyncNotification_argsTupleScheme getScheme() {
+ return new onStartConfigResyncNotification_argsTupleScheme();
+ }
+ }
+
+ private static class onStartConfigResyncNotification_argsTupleScheme extends TupleScheme<onStartConfigResyncNotification_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, onStartConfigResyncNotification_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, onStartConfigResyncNotification_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ }
+ }
+
+ }
+
+ public static class onNotificationSendEvent_args implements org.apache.thrift.TBase<onNotificationSendEvent_args, onNotificationSendEvent_args._Fields>, java.io.Serializable, Cloneable, Comparable<onNotificationSendEvent_args> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("onNotificationSendEvent_args");
+
+ private static final org.apache.thrift.protocol.TField PREFIX_FIELD_DESC = new org.apache.thrift.protocol.TField("prefix", org.apache.thrift.protocol.TType.STRING, (short)1);
+ private static final org.apache.thrift.protocol.TField ERR_CODE_FIELD_DESC = new org.apache.thrift.protocol.TField("errCode", org.apache.thrift.protocol.TType.BYTE, (short)2);
+ private static final org.apache.thrift.protocol.TField ERR_SUBCODE_FIELD_DESC = new org.apache.thrift.protocol.TField("errSubcode", org.apache.thrift.protocol.TType.BYTE, (short)3);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new onNotificationSendEvent_argsStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new onNotificationSendEvent_argsTupleSchemeFactory());
+ }
+
+ public String prefix; // required
+ public byte errCode; // required
+ public byte errSubcode; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ PREFIX((short)1, "prefix"),
+ ERR_CODE((short)2, "errCode"),
+ ERR_SUBCODE((short)3, "errSubcode");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // PREFIX
+ return PREFIX;
+ case 2: // ERR_CODE
+ return ERR_CODE;
+ case 3: // ERR_SUBCODE
+ return ERR_SUBCODE;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __ERRCODE_ISSET_ID = 0;
+ private static final int __ERRSUBCODE_ISSET_ID = 1;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.PREFIX, new org.apache.thrift.meta_data.FieldMetaData("prefix", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ tmpMap.put(_Fields.ERR_CODE, new org.apache.thrift.meta_data.FieldMetaData("errCode", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BYTE)));
+ tmpMap.put(_Fields.ERR_SUBCODE, new org.apache.thrift.meta_data.FieldMetaData("errSubcode", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.BYTE)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(onNotificationSendEvent_args.class, metaDataMap);
+ }
+
+ public onNotificationSendEvent_args() {
+ }
+
+ public onNotificationSendEvent_args(
+ String prefix,
+ byte errCode,
+ byte errSubcode)
+ {
+ this();
+ this.prefix = prefix;
+ this.errCode = errCode;
+ setErrCodeIsSet(true);
+ this.errSubcode = errSubcode;
+ setErrSubcodeIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public onNotificationSendEvent_args(onNotificationSendEvent_args other) {
+ __isset_bitfield = other.__isset_bitfield;
+ if (other.isSetPrefix()) {
+ this.prefix = other.prefix;
+ }
+ this.errCode = other.errCode;
+ this.errSubcode = other.errSubcode;
+ }
+
+ public onNotificationSendEvent_args deepCopy() {
+ return new onNotificationSendEvent_args(this);
+ }
+
+ @Override
+ public void clear() {
+ this.prefix = null;
+ setErrCodeIsSet(false);
+ this.errCode = 0;
+ setErrSubcodeIsSet(false);
+ this.errSubcode = 0;
+ }
+
+ public String getPrefix() {
+ return this.prefix;
+ }
+
+ public onNotificationSendEvent_args setPrefix(String prefix) {
+ this.prefix = prefix;
+ return this;
+ }
+
+ public void unsetPrefix() {
+ this.prefix = null;
+ }
+
+ /** Returns true if field prefix is set (has been assigned a value) and false otherwise */
+ public boolean isSetPrefix() {
+ return this.prefix != null;
+ }
+
+ public void setPrefixIsSet(boolean value) {
+ if (!value) {
+ this.prefix = null;
+ }
+ }
+
+ public byte getErrCode() {
+ return this.errCode;
+ }
+
+ public onNotificationSendEvent_args setErrCode(byte errCode) {
+ this.errCode = errCode;
+ setErrCodeIsSet(true);
+ return this;
+ }
+
+ public void unsetErrCode() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __ERRCODE_ISSET_ID);
+ }
+
+ /** Returns true if field errCode is set (has been assigned a value) and false otherwise */
+ public boolean isSetErrCode() {
+ return EncodingUtils.testBit(__isset_bitfield, __ERRCODE_ISSET_ID);
+ }
+
+ public void setErrCodeIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __ERRCODE_ISSET_ID, value);
+ }
+
+ public byte getErrSubcode() {
+ return this.errSubcode;
+ }
+
+ public onNotificationSendEvent_args setErrSubcode(byte errSubcode) {
+ this.errSubcode = errSubcode;
+ setErrSubcodeIsSet(true);
+ return this;
+ }
+
+ public void unsetErrSubcode() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __ERRSUBCODE_ISSET_ID);
+ }
+
+ /** Returns true if field errSubcode is set (has been assigned a value) and false otherwise */
+ public boolean isSetErrSubcode() {
+ return EncodingUtils.testBit(__isset_bitfield, __ERRSUBCODE_ISSET_ID);
+ }
+
+ public void setErrSubcodeIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __ERRSUBCODE_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case PREFIX:
+ if (value == null) {
+ unsetPrefix();
+ } else {
+ setPrefix((String)value);
+ }
+ break;
+
+ case ERR_CODE:
+ if (value == null) {
+ unsetErrCode();
+ } else {
+ setErrCode((Byte)value);
+ }
+ break;
+
+ case ERR_SUBCODE:
+ if (value == null) {
+ unsetErrSubcode();
+ } else {
+ setErrSubcode((Byte)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case PREFIX:
+ return getPrefix();
+
+ case ERR_CODE:
+ return Byte.valueOf(getErrCode());
+
+ case ERR_SUBCODE:
+ return Byte.valueOf(getErrSubcode());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case PREFIX:
+ return isSetPrefix();
+ case ERR_CODE:
+ return isSetErrCode();
+ case ERR_SUBCODE:
+ return isSetErrSubcode();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof onNotificationSendEvent_args)
+ return this.equals((onNotificationSendEvent_args)that);
+ return false;
+ }
+
+ public boolean equals(onNotificationSendEvent_args that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_prefix = true && this.isSetPrefix();
+ boolean that_present_prefix = true && that.isSetPrefix();
+ if (this_present_prefix || that_present_prefix) {
+ if (!(this_present_prefix && that_present_prefix))
+ return false;
+ if (!this.prefix.equals(that.prefix))
+ return false;
+ }
+
+ boolean this_present_errCode = true;
+ boolean that_present_errCode = true;
+ if (this_present_errCode || that_present_errCode) {
+ if (!(this_present_errCode && that_present_errCode))
+ return false;
+ if (this.errCode != that.errCode)
+ return false;
+ }
+
+ boolean this_present_errSubcode = true;
+ boolean that_present_errSubcode = true;
+ if (this_present_errSubcode || that_present_errSubcode) {
+ if (!(this_present_errSubcode && that_present_errSubcode))
+ return false;
+ if (this.errSubcode != that.errSubcode)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(onNotificationSendEvent_args other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetPrefix()).compareTo(other.isSetPrefix());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetPrefix()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.prefix, other.prefix);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetErrCode()).compareTo(other.isSetErrCode());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetErrCode()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.errCode, other.errCode);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetErrSubcode()).compareTo(other.isSetErrSubcode());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetErrSubcode()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.errSubcode, other.errSubcode);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("onNotificationSendEvent_args(");
+ boolean first = true;
+
+ sb.append("prefix:");
+ if (this.prefix == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.prefix);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("errCode:");
+ sb.append(this.errCode);
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("errSubcode:");
+ sb.append(this.errSubcode);
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class onNotificationSendEvent_argsStandardSchemeFactory implements SchemeFactory {
+ public onNotificationSendEvent_argsStandardScheme getScheme() {
+ return new onNotificationSendEvent_argsStandardScheme();
+ }
+ }
+
+ private static class onNotificationSendEvent_argsStandardScheme extends StandardScheme<onNotificationSendEvent_args> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, onNotificationSendEvent_args struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // PREFIX
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.prefix = iprot.readString();
+ struct.setPrefixIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 2: // ERR_CODE
+ if (schemeField.type == org.apache.thrift.protocol.TType.BYTE) {
+ struct.errCode = iprot.readByte();
+ struct.setErrCodeIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 3: // ERR_SUBCODE
+ if (schemeField.type == org.apache.thrift.protocol.TType.BYTE) {
+ struct.errSubcode = iprot.readByte();
+ struct.setErrSubcodeIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, onNotificationSendEvent_args struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ if (struct.prefix != null) {
+ oprot.writeFieldBegin(PREFIX_FIELD_DESC);
+ oprot.writeString(struct.prefix);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldBegin(ERR_CODE_FIELD_DESC);
+ oprot.writeByte(struct.errCode);
+ oprot.writeFieldEnd();
+ oprot.writeFieldBegin(ERR_SUBCODE_FIELD_DESC);
+ oprot.writeByte(struct.errSubcode);
+ oprot.writeFieldEnd();
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class onNotificationSendEvent_argsTupleSchemeFactory implements SchemeFactory {
+ public onNotificationSendEvent_argsTupleScheme getScheme() {
+ return new onNotificationSendEvent_argsTupleScheme();
+ }
+ }
+
+ private static class onNotificationSendEvent_argsTupleScheme extends TupleScheme<onNotificationSendEvent_args> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, onNotificationSendEvent_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetPrefix()) {
+ optionals.set(0);
+ }
+ if (struct.isSetErrCode()) {
+ optionals.set(1);
+ }
+ if (struct.isSetErrSubcode()) {
+ optionals.set(2);
+ }
+ oprot.writeBitSet(optionals, 3);
+ if (struct.isSetPrefix()) {
+ oprot.writeString(struct.prefix);
+ }
+ if (struct.isSetErrCode()) {
+ oprot.writeByte(struct.errCode);
+ }
+ if (struct.isSetErrSubcode()) {
+ oprot.writeByte(struct.errSubcode);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, onNotificationSendEvent_args struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(3);
+ if (incoming.get(0)) {
+ struct.prefix = iprot.readString();
+ struct.setPrefixIsSet(true);
+ }
+ if (incoming.get(1)) {
+ struct.errCode = iprot.readByte();
+ struct.setErrCodeIsSet(true);
+ }
+ if (incoming.get(2)) {
+ struct.errSubcode = iprot.readByte();
+ struct.setErrSubcodeIsSet(true);
+ }
+ }
+ }
+
+ }
+
+}
--- /dev/null
+/**
+ * Autogenerated by Thrift Compiler (0.9.1)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ * @generated
+ */
+
+package org.opendaylight.bgpmanager.thrift.gen;
+
+import org.apache.thrift.scheme.IScheme;
+import org.apache.thrift.scheme.SchemeFactory;
+import org.apache.thrift.scheme.StandardScheme;
+
+import org.apache.thrift.scheme.TupleScheme;
+import org.apache.thrift.protocol.TTupleProtocol;
+import org.apache.thrift.protocol.TProtocolException;
+import org.apache.thrift.EncodingUtils;
+import org.apache.thrift.TException;
+import org.apache.thrift.async.AsyncMethodCallback;
+import org.apache.thrift.server.AbstractNonblockingServer.*;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.EnumMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.EnumSet;
+import java.util.Collections;
+import java.util.BitSet;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Routes implements org.apache.thrift.TBase<Routes, Routes._Fields>, java.io.Serializable, Cloneable, Comparable<Routes> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("Routes");
+
+ private static final org.apache.thrift.protocol.TField ERRCODE_FIELD_DESC = new org.apache.thrift.protocol.TField("errcode", org.apache.thrift.protocol.TType.I32, (short)1);
+ private static final org.apache.thrift.protocol.TField UPDATES_FIELD_DESC = new org.apache.thrift.protocol.TField("updates", org.apache.thrift.protocol.TType.LIST, (short)2);
+ private static final org.apache.thrift.protocol.TField MORE_FIELD_DESC = new org.apache.thrift.protocol.TField("more", org.apache.thrift.protocol.TType.I32, (short)4);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new RoutesStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new RoutesTupleSchemeFactory());
+ }
+
+ public int errcode; // required
+ public List<Update> updates; // optional
+ public int more; // optional
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ ERRCODE((short)1, "errcode"),
+ UPDATES((short)2, "updates"),
+ MORE((short)4, "more");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // ERRCODE
+ return ERRCODE;
+ case 2: // UPDATES
+ return UPDATES;
+ case 4: // MORE
+ return MORE;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __ERRCODE_ISSET_ID = 0;
+ private static final int __MORE_ISSET_ID = 1;
+ private byte __isset_bitfield = 0;
+ private _Fields optionals[] = {_Fields.UPDATES,_Fields.MORE};
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.ERRCODE, new org.apache.thrift.meta_data.FieldMetaData("errcode", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ tmpMap.put(_Fields.UPDATES, new org.apache.thrift.meta_data.FieldMetaData("updates", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+ new org.apache.thrift.meta_data.ListMetaData(org.apache.thrift.protocol.TType.LIST,
+ new org.apache.thrift.meta_data.StructMetaData(org.apache.thrift.protocol.TType.STRUCT, Update.class))));
+ tmpMap.put(_Fields.MORE, new org.apache.thrift.meta_data.FieldMetaData("more", org.apache.thrift.TFieldRequirementType.OPTIONAL,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(Routes.class, metaDataMap);
+ }
+
+ public Routes() {
+ }
+
+ public Routes(
+ int errcode)
+ {
+ this();
+ this.errcode = errcode;
+ setErrcodeIsSet(true);
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public Routes(Routes other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.errcode = other.errcode;
+ if (other.isSetUpdates()) {
+ List<Update> __this__updates = new ArrayList<Update>(other.updates.size());
+ for (Update other_element : other.updates) {
+ __this__updates.add(new Update(other_element));
+ }
+ this.updates = __this__updates;
+ }
+ this.more = other.more;
+ }
+
+ public Routes deepCopy() {
+ return new Routes(this);
+ }
+
+ @Override
+ public void clear() {
+ setErrcodeIsSet(false);
+ this.errcode = 0;
+ this.updates = null;
+ setMoreIsSet(false);
+ this.more = 0;
+ }
+
+ public int getErrcode() {
+ return this.errcode;
+ }
+
+ public Routes setErrcode(int errcode) {
+ this.errcode = errcode;
+ setErrcodeIsSet(true);
+ return this;
+ }
+
+ public void unsetErrcode() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __ERRCODE_ISSET_ID);
+ }
+
+ /** Returns true if field errcode is set (has been assigned a value) and false otherwise */
+ public boolean isSetErrcode() {
+ return EncodingUtils.testBit(__isset_bitfield, __ERRCODE_ISSET_ID);
+ }
+
+ public void setErrcodeIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __ERRCODE_ISSET_ID, value);
+ }
+
+ public int getUpdatesSize() {
+ return (this.updates == null) ? 0 : this.updates.size();
+ }
+
+ public java.util.Iterator<Update> getUpdatesIterator() {
+ return (this.updates == null) ? null : this.updates.iterator();
+ }
+
+ public void addToUpdates(Update elem) {
+ if (this.updates == null) {
+ this.updates = new ArrayList<Update>();
+ }
+ this.updates.add(elem);
+ }
+
+ public List<Update> getUpdates() {
+ return this.updates;
+ }
+
+ public Routes setUpdates(List<Update> updates) {
+ this.updates = updates;
+ return this;
+ }
+
+ public void unsetUpdates() {
+ this.updates = null;
+ }
+
+ /** Returns true if field updates is set (has been assigned a value) and false otherwise */
+ public boolean isSetUpdates() {
+ return this.updates != null;
+ }
+
+ public void setUpdatesIsSet(boolean value) {
+ if (!value) {
+ this.updates = null;
+ }
+ }
+
+ public int getMore() {
+ return this.more;
+ }
+
+ public Routes setMore(int more) {
+ this.more = more;
+ setMoreIsSet(true);
+ return this;
+ }
+
+ public void unsetMore() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __MORE_ISSET_ID);
+ }
+
+ /** Returns true if field more is set (has been assigned a value) and false otherwise */
+ public boolean isSetMore() {
+ return EncodingUtils.testBit(__isset_bitfield, __MORE_ISSET_ID);
+ }
+
+ public void setMoreIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __MORE_ISSET_ID, value);
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case ERRCODE:
+ if (value == null) {
+ unsetErrcode();
+ } else {
+ setErrcode((Integer)value);
+ }
+ break;
+
+ case UPDATES:
+ if (value == null) {
+ unsetUpdates();
+ } else {
+ setUpdates((List<Update>)value);
+ }
+ break;
+
+ case MORE:
+ if (value == null) {
+ unsetMore();
+ } else {
+ setMore((Integer)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case ERRCODE:
+ return Integer.valueOf(getErrcode());
+
+ case UPDATES:
+ return getUpdates();
+
+ case MORE:
+ return Integer.valueOf(getMore());
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case ERRCODE:
+ return isSetErrcode();
+ case UPDATES:
+ return isSetUpdates();
+ case MORE:
+ return isSetMore();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof Routes)
+ return this.equals((Routes)that);
+ return false;
+ }
+
+ public boolean equals(Routes that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_errcode = true;
+ boolean that_present_errcode = true;
+ if (this_present_errcode || that_present_errcode) {
+ if (!(this_present_errcode && that_present_errcode))
+ return false;
+ if (this.errcode != that.errcode)
+ return false;
+ }
+
+ boolean this_present_updates = true && this.isSetUpdates();
+ boolean that_present_updates = true && that.isSetUpdates();
+ if (this_present_updates || that_present_updates) {
+ if (!(this_present_updates && that_present_updates))
+ return false;
+ if (!this.updates.equals(that.updates))
+ return false;
+ }
+
+ boolean this_present_more = true && this.isSetMore();
+ boolean that_present_more = true && that.isSetMore();
+ if (this_present_more || that_present_more) {
+ if (!(this_present_more && that_present_more))
+ return false;
+ if (this.more != that.more)
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(Routes other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetErrcode()).compareTo(other.isSetErrcode());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetErrcode()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.errcode, other.errcode);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetUpdates()).compareTo(other.isSetUpdates());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetUpdates()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.updates, other.updates);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetMore()).compareTo(other.isSetMore());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetMore()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.more, other.more);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("Routes(");
+ boolean first = true;
+
+ sb.append("errcode:");
+ sb.append(this.errcode);
+ first = false;
+ if (isSetUpdates()) {
+ if (!first) sb.append(", ");
+ sb.append("updates:");
+ if (this.updates == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.updates);
+ }
+ first = false;
+ }
+ if (isSetMore()) {
+ if (!first) sb.append(", ");
+ sb.append("more:");
+ sb.append(this.more);
+ first = false;
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class RoutesStandardSchemeFactory implements SchemeFactory {
+ public RoutesStandardScheme getScheme() {
+ return new RoutesStandardScheme();
+ }
+ }
+
+ private static class RoutesStandardScheme extends StandardScheme<Routes> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, Routes struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // ERRCODE
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.errcode = iprot.readI32();
+ struct.setErrcodeIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 2: // UPDATES
+ if (schemeField.type == org.apache.thrift.protocol.TType.LIST) {
+ {
+ org.apache.thrift.protocol.TList _list0 = iprot.readListBegin();
+ struct.updates = new ArrayList<Update>(_list0.size);
+ for (int _i1 = 0; _i1 < _list0.size; ++_i1)
+ {
+ Update _elem2;
+ _elem2 = new Update();
+ _elem2.read(iprot);
+ struct.updates.add(_elem2);
+ }
+ iprot.readListEnd();
+ }
+ struct.setUpdatesIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 4: // MORE
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.more = iprot.readI32();
+ struct.setMoreIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, Routes struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ oprot.writeFieldBegin(ERRCODE_FIELD_DESC);
+ oprot.writeI32(struct.errcode);
+ oprot.writeFieldEnd();
+ if (struct.updates != null) {
+ if (struct.isSetUpdates()) {
+ oprot.writeFieldBegin(UPDATES_FIELD_DESC);
+ {
+ oprot.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, struct.updates.size()));
+ for (Update _iter3 : struct.updates)
+ {
+ _iter3.write(oprot);
+ }
+ oprot.writeListEnd();
+ }
+ oprot.writeFieldEnd();
+ }
+ }
+ if (struct.isSetMore()) {
+ oprot.writeFieldBegin(MORE_FIELD_DESC);
+ oprot.writeI32(struct.more);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class RoutesTupleSchemeFactory implements SchemeFactory {
+ public RoutesTupleScheme getScheme() {
+ return new RoutesTupleScheme();
+ }
+ }
+
+ private static class RoutesTupleScheme extends TupleScheme<Routes> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, Routes struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetErrcode()) {
+ optionals.set(0);
+ }
+ if (struct.isSetUpdates()) {
+ optionals.set(1);
+ }
+ if (struct.isSetMore()) {
+ optionals.set(2);
+ }
+ oprot.writeBitSet(optionals, 3);
+ if (struct.isSetErrcode()) {
+ oprot.writeI32(struct.errcode);
+ }
+ if (struct.isSetUpdates()) {
+ {
+ oprot.writeI32(struct.updates.size());
+ for (Update _iter4 : struct.updates)
+ {
+ _iter4.write(oprot);
+ }
+ }
+ }
+ if (struct.isSetMore()) {
+ oprot.writeI32(struct.more);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, Routes struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(3);
+ if (incoming.get(0)) {
+ struct.errcode = iprot.readI32();
+ struct.setErrcodeIsSet(true);
+ }
+ if (incoming.get(1)) {
+ {
+ org.apache.thrift.protocol.TList _list5 = new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, iprot.readI32());
+ struct.updates = new ArrayList<Update>(_list5.size);
+ for (int _i6 = 0; _i6 < _list5.size; ++_i6)
+ {
+ Update _elem7;
+ _elem7 = new Update();
+ _elem7.read(iprot);
+ struct.updates.add(_elem7);
+ }
+ }
+ struct.setUpdatesIsSet(true);
+ }
+ if (incoming.get(2)) {
+ struct.more = iprot.readI32();
+ struct.setMoreIsSet(true);
+ }
+ }
+ }
+
+}
+
--- /dev/null
+/**
+ * Autogenerated by Thrift Compiler (0.9.1)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ * @generated
+ */
+
+package org.opendaylight.bgpmanager.thrift.gen;
+
+import org.apache.thrift.scheme.IScheme;
+import org.apache.thrift.scheme.SchemeFactory;
+import org.apache.thrift.scheme.StandardScheme;
+
+import org.apache.thrift.scheme.TupleScheme;
+import org.apache.thrift.protocol.TTupleProtocol;
+import org.apache.thrift.protocol.TProtocolException;
+import org.apache.thrift.EncodingUtils;
+import org.apache.thrift.TException;
+import org.apache.thrift.async.AsyncMethodCallback;
+import org.apache.thrift.server.AbstractNonblockingServer.*;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.EnumMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.EnumSet;
+import java.util.Collections;
+import java.util.BitSet;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Update implements org.apache.thrift.TBase<Update, Update._Fields>, java.io.Serializable, Cloneable, Comparable<Update> {
+ private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("Update");
+
+ private static final org.apache.thrift.protocol.TField TYPE_FIELD_DESC = new org.apache.thrift.protocol.TField("type", org.apache.thrift.protocol.TType.I32, (short)1);
+ private static final org.apache.thrift.protocol.TField RESERVED_FIELD_DESC = new org.apache.thrift.protocol.TField("reserved", org.apache.thrift.protocol.TType.I32, (short)2);
+ private static final org.apache.thrift.protocol.TField PREFIXLEN_FIELD_DESC = new org.apache.thrift.protocol.TField("prefixlen", org.apache.thrift.protocol.TType.I32, (short)3);
+ private static final org.apache.thrift.protocol.TField LABEL_FIELD_DESC = new org.apache.thrift.protocol.TField("label", org.apache.thrift.protocol.TType.I32, (short)4);
+ private static final org.apache.thrift.protocol.TField RD_FIELD_DESC = new org.apache.thrift.protocol.TField("rd", org.apache.thrift.protocol.TType.STRING, (short)5);
+ private static final org.apache.thrift.protocol.TField PREFIX_FIELD_DESC = new org.apache.thrift.protocol.TField("prefix", org.apache.thrift.protocol.TType.STRING, (short)6);
+ private static final org.apache.thrift.protocol.TField NEXTHOP_FIELD_DESC = new org.apache.thrift.protocol.TField("nexthop", org.apache.thrift.protocol.TType.STRING, (short)7);
+
+ private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
+ static {
+ schemes.put(StandardScheme.class, new UpdateStandardSchemeFactory());
+ schemes.put(TupleScheme.class, new UpdateTupleSchemeFactory());
+ }
+
+ public int type; // required
+ public int reserved; // required
+ public int prefixlen; // required
+ public int label; // required
+ public String rd; // required
+ public String prefix; // required
+ public String nexthop; // required
+
+ /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
+ public enum _Fields implements org.apache.thrift.TFieldIdEnum {
+ TYPE((short)1, "type"),
+ RESERVED((short)2, "reserved"),
+ PREFIXLEN((short)3, "prefixlen"),
+ LABEL((short)4, "label"),
+ RD((short)5, "rd"),
+ PREFIX((short)6, "prefix"),
+ NEXTHOP((short)7, "nexthop");
+
+ private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
+
+ static {
+ for (_Fields field : EnumSet.allOf(_Fields.class)) {
+ byName.put(field.getFieldName(), field);
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, or null if its not found.
+ */
+ public static _Fields findByThriftId(int fieldId) {
+ switch(fieldId) {
+ case 1: // TYPE
+ return TYPE;
+ case 2: // RESERVED
+ return RESERVED;
+ case 3: // PREFIXLEN
+ return PREFIXLEN;
+ case 4: // LABEL
+ return LABEL;
+ case 5: // RD
+ return RD;
+ case 6: // PREFIX
+ return PREFIX;
+ case 7: // NEXTHOP
+ return NEXTHOP;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Find the _Fields constant that matches fieldId, throwing an exception
+ * if it is not found.
+ */
+ public static _Fields findByThriftIdOrThrow(int fieldId) {
+ _Fields fields = findByThriftId(fieldId);
+ if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!");
+ return fields;
+ }
+
+ /**
+ * Find the _Fields constant that matches name, or null if its not found.
+ */
+ public static _Fields findByName(String name) {
+ return byName.get(name);
+ }
+
+ private final short _thriftId;
+ private final String _fieldName;
+
+ _Fields(short thriftId, String fieldName) {
+ _thriftId = thriftId;
+ _fieldName = fieldName;
+ }
+
+ public short getThriftFieldId() {
+ return _thriftId;
+ }
+
+ public String getFieldName() {
+ return _fieldName;
+ }
+ }
+
+ // isset id assignments
+ private static final int __TYPE_ISSET_ID = 0;
+ private static final int __RESERVED_ISSET_ID = 1;
+ private static final int __PREFIXLEN_ISSET_ID = 2;
+ private static final int __LABEL_ISSET_ID = 3;
+ private byte __isset_bitfield = 0;
+ public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap;
+ static {
+ Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class);
+ tmpMap.put(_Fields.TYPE, new org.apache.thrift.meta_data.FieldMetaData("type", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ tmpMap.put(_Fields.RESERVED, new org.apache.thrift.meta_data.FieldMetaData("reserved", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ tmpMap.put(_Fields.PREFIXLEN, new org.apache.thrift.meta_data.FieldMetaData("prefixlen", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ tmpMap.put(_Fields.LABEL, new org.apache.thrift.meta_data.FieldMetaData("label", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32)));
+ tmpMap.put(_Fields.RD, new org.apache.thrift.meta_data.FieldMetaData("rd", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ tmpMap.put(_Fields.PREFIX, new org.apache.thrift.meta_data.FieldMetaData("prefix", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ tmpMap.put(_Fields.NEXTHOP, new org.apache.thrift.meta_data.FieldMetaData("nexthop", org.apache.thrift.TFieldRequirementType.DEFAULT,
+ new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
+ metaDataMap = Collections.unmodifiableMap(tmpMap);
+ org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(Update.class, metaDataMap);
+ }
+
+ public Update() {
+ }
+
+ public Update(
+ int type,
+ int reserved,
+ int prefixlen,
+ int label,
+ String rd,
+ String prefix,
+ String nexthop)
+ {
+ this();
+ this.type = type;
+ setTypeIsSet(true);
+ this.reserved = reserved;
+ setReservedIsSet(true);
+ this.prefixlen = prefixlen;
+ setPrefixlenIsSet(true);
+ this.label = label;
+ setLabelIsSet(true);
+ this.rd = rd;
+ this.prefix = prefix;
+ this.nexthop = nexthop;
+ }
+
+ /**
+ * Performs a deep copy on <i>other</i>.
+ */
+ public Update(Update other) {
+ __isset_bitfield = other.__isset_bitfield;
+ this.type = other.type;
+ this.reserved = other.reserved;
+ this.prefixlen = other.prefixlen;
+ this.label = other.label;
+ if (other.isSetRd()) {
+ this.rd = other.rd;
+ }
+ if (other.isSetPrefix()) {
+ this.prefix = other.prefix;
+ }
+ if (other.isSetNexthop()) {
+ this.nexthop = other.nexthop;
+ }
+ }
+
+ public Update deepCopy() {
+ return new Update(this);
+ }
+
+ @Override
+ public void clear() {
+ setTypeIsSet(false);
+ this.type = 0;
+ setReservedIsSet(false);
+ this.reserved = 0;
+ setPrefixlenIsSet(false);
+ this.prefixlen = 0;
+ setLabelIsSet(false);
+ this.label = 0;
+ this.rd = null;
+ this.prefix = null;
+ this.nexthop = null;
+ }
+
+ public int getType() {
+ return this.type;
+ }
+
+ public Update setType(int type) {
+ this.type = type;
+ setTypeIsSet(true);
+ return this;
+ }
+
+ public void unsetType() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __TYPE_ISSET_ID);
+ }
+
+ /** Returns true if field type is set (has been assigned a value) and false otherwise */
+ public boolean isSetType() {
+ return EncodingUtils.testBit(__isset_bitfield, __TYPE_ISSET_ID);
+ }
+
+ public void setTypeIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __TYPE_ISSET_ID, value);
+ }
+
+ public int getReserved() {
+ return this.reserved;
+ }
+
+ public Update setReserved(int reserved) {
+ this.reserved = reserved;
+ setReservedIsSet(true);
+ return this;
+ }
+
+ public void unsetReserved() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __RESERVED_ISSET_ID);
+ }
+
+ /** Returns true if field reserved is set (has been assigned a value) and false otherwise */
+ public boolean isSetReserved() {
+ return EncodingUtils.testBit(__isset_bitfield, __RESERVED_ISSET_ID);
+ }
+
+ public void setReservedIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __RESERVED_ISSET_ID, value);
+ }
+
+ public int getPrefixlen() {
+ return this.prefixlen;
+ }
+
+ public Update setPrefixlen(int prefixlen) {
+ this.prefixlen = prefixlen;
+ setPrefixlenIsSet(true);
+ return this;
+ }
+
+ public void unsetPrefixlen() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __PREFIXLEN_ISSET_ID);
+ }
+
+ /** Returns true if field prefixlen is set (has been assigned a value) and false otherwise */
+ public boolean isSetPrefixlen() {
+ return EncodingUtils.testBit(__isset_bitfield, __PREFIXLEN_ISSET_ID);
+ }
+
+ public void setPrefixlenIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __PREFIXLEN_ISSET_ID, value);
+ }
+
+ public int getLabel() {
+ return this.label;
+ }
+
+ public Update setLabel(int label) {
+ this.label = label;
+ setLabelIsSet(true);
+ return this;
+ }
+
+ public void unsetLabel() {
+ __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __LABEL_ISSET_ID);
+ }
+
+ /** Returns true if field label is set (has been assigned a value) and false otherwise */
+ public boolean isSetLabel() {
+ return EncodingUtils.testBit(__isset_bitfield, __LABEL_ISSET_ID);
+ }
+
+ public void setLabelIsSet(boolean value) {
+ __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __LABEL_ISSET_ID, value);
+ }
+
+ public String getRd() {
+ return this.rd;
+ }
+
+ public Update setRd(String rd) {
+ this.rd = rd;
+ return this;
+ }
+
+ public void unsetRd() {
+ this.rd = null;
+ }
+
+ /** Returns true if field rd is set (has been assigned a value) and false otherwise */
+ public boolean isSetRd() {
+ return this.rd != null;
+ }
+
+ public void setRdIsSet(boolean value) {
+ if (!value) {
+ this.rd = null;
+ }
+ }
+
+ public String getPrefix() {
+ return this.prefix;
+ }
+
+ public Update setPrefix(String prefix) {
+ this.prefix = prefix;
+ return this;
+ }
+
+ public void unsetPrefix() {
+ this.prefix = null;
+ }
+
+ /** Returns true if field prefix is set (has been assigned a value) and false otherwise */
+ public boolean isSetPrefix() {
+ return this.prefix != null;
+ }
+
+ public void setPrefixIsSet(boolean value) {
+ if (!value) {
+ this.prefix = null;
+ }
+ }
+
+ public String getNexthop() {
+ return this.nexthop;
+ }
+
+ public Update setNexthop(String nexthop) {
+ this.nexthop = nexthop;
+ return this;
+ }
+
+ public void unsetNexthop() {
+ this.nexthop = null;
+ }
+
+ /** Returns true if field nexthop is set (has been assigned a value) and false otherwise */
+ public boolean isSetNexthop() {
+ return this.nexthop != null;
+ }
+
+ public void setNexthopIsSet(boolean value) {
+ if (!value) {
+ this.nexthop = null;
+ }
+ }
+
+ public void setFieldValue(_Fields field, Object value) {
+ switch (field) {
+ case TYPE:
+ if (value == null) {
+ unsetType();
+ } else {
+ setType((Integer)value);
+ }
+ break;
+
+ case RESERVED:
+ if (value == null) {
+ unsetReserved();
+ } else {
+ setReserved((Integer)value);
+ }
+ break;
+
+ case PREFIXLEN:
+ if (value == null) {
+ unsetPrefixlen();
+ } else {
+ setPrefixlen((Integer)value);
+ }
+ break;
+
+ case LABEL:
+ if (value == null) {
+ unsetLabel();
+ } else {
+ setLabel((Integer)value);
+ }
+ break;
+
+ case RD:
+ if (value == null) {
+ unsetRd();
+ } else {
+ setRd((String)value);
+ }
+ break;
+
+ case PREFIX:
+ if (value == null) {
+ unsetPrefix();
+ } else {
+ setPrefix((String)value);
+ }
+ break;
+
+ case NEXTHOP:
+ if (value == null) {
+ unsetNexthop();
+ } else {
+ setNexthop((String)value);
+ }
+ break;
+
+ }
+ }
+
+ public Object getFieldValue(_Fields field) {
+ switch (field) {
+ case TYPE:
+ return Integer.valueOf(getType());
+
+ case RESERVED:
+ return Integer.valueOf(getReserved());
+
+ case PREFIXLEN:
+ return Integer.valueOf(getPrefixlen());
+
+ case LABEL:
+ return Integer.valueOf(getLabel());
+
+ case RD:
+ return getRd();
+
+ case PREFIX:
+ return getPrefix();
+
+ case NEXTHOP:
+ return getNexthop();
+
+ }
+ throw new IllegalStateException();
+ }
+
+ /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */
+ public boolean isSet(_Fields field) {
+ if (field == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (field) {
+ case TYPE:
+ return isSetType();
+ case RESERVED:
+ return isSetReserved();
+ case PREFIXLEN:
+ return isSetPrefixlen();
+ case LABEL:
+ return isSetLabel();
+ case RD:
+ return isSetRd();
+ case PREFIX:
+ return isSetPrefix();
+ case NEXTHOP:
+ return isSetNexthop();
+ }
+ throw new IllegalStateException();
+ }
+
+ @Override
+ public boolean equals(Object that) {
+ if (that == null)
+ return false;
+ if (that instanceof Update)
+ return this.equals((Update)that);
+ return false;
+ }
+
+ public boolean equals(Update that) {
+ if (that == null)
+ return false;
+
+ boolean this_present_type = true;
+ boolean that_present_type = true;
+ if (this_present_type || that_present_type) {
+ if (!(this_present_type && that_present_type))
+ return false;
+ if (this.type != that.type)
+ return false;
+ }
+
+ boolean this_present_reserved = true;
+ boolean that_present_reserved = true;
+ if (this_present_reserved || that_present_reserved) {
+ if (!(this_present_reserved && that_present_reserved))
+ return false;
+ if (this.reserved != that.reserved)
+ return false;
+ }
+
+ boolean this_present_prefixlen = true;
+ boolean that_present_prefixlen = true;
+ if (this_present_prefixlen || that_present_prefixlen) {
+ if (!(this_present_prefixlen && that_present_prefixlen))
+ return false;
+ if (this.prefixlen != that.prefixlen)
+ return false;
+ }
+
+ boolean this_present_label = true;
+ boolean that_present_label = true;
+ if (this_present_label || that_present_label) {
+ if (!(this_present_label && that_present_label))
+ return false;
+ if (this.label != that.label)
+ return false;
+ }
+
+ boolean this_present_rd = true && this.isSetRd();
+ boolean that_present_rd = true && that.isSetRd();
+ if (this_present_rd || that_present_rd) {
+ if (!(this_present_rd && that_present_rd))
+ return false;
+ if (!this.rd.equals(that.rd))
+ return false;
+ }
+
+ boolean this_present_prefix = true && this.isSetPrefix();
+ boolean that_present_prefix = true && that.isSetPrefix();
+ if (this_present_prefix || that_present_prefix) {
+ if (!(this_present_prefix && that_present_prefix))
+ return false;
+ if (!this.prefix.equals(that.prefix))
+ return false;
+ }
+
+ boolean this_present_nexthop = true && this.isSetNexthop();
+ boolean that_present_nexthop = true && that.isSetNexthop();
+ if (this_present_nexthop || that_present_nexthop) {
+ if (!(this_present_nexthop && that_present_nexthop))
+ return false;
+ if (!this.nexthop.equals(that.nexthop))
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public int compareTo(Update other) {
+ if (!getClass().equals(other.getClass())) {
+ return getClass().getName().compareTo(other.getClass().getName());
+ }
+
+ int lastComparison = 0;
+
+ lastComparison = Boolean.valueOf(isSetType()).compareTo(other.isSetType());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetType()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.type, other.type);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetReserved()).compareTo(other.isSetReserved());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetReserved()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.reserved, other.reserved);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetPrefixlen()).compareTo(other.isSetPrefixlen());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetPrefixlen()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.prefixlen, other.prefixlen);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetLabel()).compareTo(other.isSetLabel());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetLabel()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.label, other.label);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetRd()).compareTo(other.isSetRd());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetRd()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.rd, other.rd);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetPrefix()).compareTo(other.isSetPrefix());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetPrefix()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.prefix, other.prefix);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ lastComparison = Boolean.valueOf(isSetNexthop()).compareTo(other.isSetNexthop());
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ if (isSetNexthop()) {
+ lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.nexthop, other.nexthop);
+ if (lastComparison != 0) {
+ return lastComparison;
+ }
+ }
+ return 0;
+ }
+
+ public _Fields fieldForId(int fieldId) {
+ return _Fields.findByThriftId(fieldId);
+ }
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException {
+ schemes.get(iprot.getScheme()).getScheme().read(iprot, this);
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException {
+ schemes.get(oprot.getScheme()).getScheme().write(oprot, this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("Update(");
+ boolean first = true;
+
+ sb.append("type:");
+ sb.append(this.type);
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("reserved:");
+ sb.append(this.reserved);
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("prefixlen:");
+ sb.append(this.prefixlen);
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("label:");
+ sb.append(this.label);
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("rd:");
+ if (this.rd == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.rd);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("prefix:");
+ if (this.prefix == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.prefix);
+ }
+ first = false;
+ if (!first) sb.append(", ");
+ sb.append("nexthop:");
+ if (this.nexthop == null) {
+ sb.append("null");
+ } else {
+ sb.append(this.nexthop);
+ }
+ first = false;
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public void validate() throws org.apache.thrift.TException {
+ // check for required fields
+ // check for sub-struct validity
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
+ try {
+ write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException {
+ try {
+ // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor.
+ __isset_bitfield = 0;
+ read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in)));
+ } catch (org.apache.thrift.TException te) {
+ throw new java.io.IOException(te);
+ }
+ }
+
+ private static class UpdateStandardSchemeFactory implements SchemeFactory {
+ public UpdateStandardScheme getScheme() {
+ return new UpdateStandardScheme();
+ }
+ }
+
+ private static class UpdateStandardScheme extends StandardScheme<Update> {
+
+ public void read(org.apache.thrift.protocol.TProtocol iprot, Update struct) throws org.apache.thrift.TException {
+ org.apache.thrift.protocol.TField schemeField;
+ iprot.readStructBegin();
+ while (true)
+ {
+ schemeField = iprot.readFieldBegin();
+ if (schemeField.type == org.apache.thrift.protocol.TType.STOP) {
+ break;
+ }
+ switch (schemeField.id) {
+ case 1: // TYPE
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.type = iprot.readI32();
+ struct.setTypeIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 2: // RESERVED
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.reserved = iprot.readI32();
+ struct.setReservedIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 3: // PREFIXLEN
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.prefixlen = iprot.readI32();
+ struct.setPrefixlenIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 4: // LABEL
+ if (schemeField.type == org.apache.thrift.protocol.TType.I32) {
+ struct.label = iprot.readI32();
+ struct.setLabelIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 5: // RD
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.rd = iprot.readString();
+ struct.setRdIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 6: // PREFIX
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.prefix = iprot.readString();
+ struct.setPrefixIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ case 7: // NEXTHOP
+ if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
+ struct.nexthop = iprot.readString();
+ struct.setNexthopIsSet(true);
+ } else {
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ break;
+ default:
+ org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
+ }
+ iprot.readFieldEnd();
+ }
+ iprot.readStructEnd();
+
+ // check for required fields of primitive type, which can't be checked in the validate method
+ struct.validate();
+ }
+
+ public void write(org.apache.thrift.protocol.TProtocol oprot, Update struct) throws org.apache.thrift.TException {
+ struct.validate();
+
+ oprot.writeStructBegin(STRUCT_DESC);
+ oprot.writeFieldBegin(TYPE_FIELD_DESC);
+ oprot.writeI32(struct.type);
+ oprot.writeFieldEnd();
+ oprot.writeFieldBegin(RESERVED_FIELD_DESC);
+ oprot.writeI32(struct.reserved);
+ oprot.writeFieldEnd();
+ oprot.writeFieldBegin(PREFIXLEN_FIELD_DESC);
+ oprot.writeI32(struct.prefixlen);
+ oprot.writeFieldEnd();
+ oprot.writeFieldBegin(LABEL_FIELD_DESC);
+ oprot.writeI32(struct.label);
+ oprot.writeFieldEnd();
+ if (struct.rd != null) {
+ oprot.writeFieldBegin(RD_FIELD_DESC);
+ oprot.writeString(struct.rd);
+ oprot.writeFieldEnd();
+ }
+ if (struct.prefix != null) {
+ oprot.writeFieldBegin(PREFIX_FIELD_DESC);
+ oprot.writeString(struct.prefix);
+ oprot.writeFieldEnd();
+ }
+ if (struct.nexthop != null) {
+ oprot.writeFieldBegin(NEXTHOP_FIELD_DESC);
+ oprot.writeString(struct.nexthop);
+ oprot.writeFieldEnd();
+ }
+ oprot.writeFieldStop();
+ oprot.writeStructEnd();
+ }
+
+ }
+
+ private static class UpdateTupleSchemeFactory implements SchemeFactory {
+ public UpdateTupleScheme getScheme() {
+ return new UpdateTupleScheme();
+ }
+ }
+
+ private static class UpdateTupleScheme extends TupleScheme<Update> {
+
+ @Override
+ public void write(org.apache.thrift.protocol.TProtocol prot, Update struct) throws org.apache.thrift.TException {
+ TTupleProtocol oprot = (TTupleProtocol) prot;
+ BitSet optionals = new BitSet();
+ if (struct.isSetType()) {
+ optionals.set(0);
+ }
+ if (struct.isSetReserved()) {
+ optionals.set(1);
+ }
+ if (struct.isSetPrefixlen()) {
+ optionals.set(2);
+ }
+ if (struct.isSetLabel()) {
+ optionals.set(3);
+ }
+ if (struct.isSetRd()) {
+ optionals.set(4);
+ }
+ if (struct.isSetPrefix()) {
+ optionals.set(5);
+ }
+ if (struct.isSetNexthop()) {
+ optionals.set(6);
+ }
+ oprot.writeBitSet(optionals, 7);
+ if (struct.isSetType()) {
+ oprot.writeI32(struct.type);
+ }
+ if (struct.isSetReserved()) {
+ oprot.writeI32(struct.reserved);
+ }
+ if (struct.isSetPrefixlen()) {
+ oprot.writeI32(struct.prefixlen);
+ }
+ if (struct.isSetLabel()) {
+ oprot.writeI32(struct.label);
+ }
+ if (struct.isSetRd()) {
+ oprot.writeString(struct.rd);
+ }
+ if (struct.isSetPrefix()) {
+ oprot.writeString(struct.prefix);
+ }
+ if (struct.isSetNexthop()) {
+ oprot.writeString(struct.nexthop);
+ }
+ }
+
+ @Override
+ public void read(org.apache.thrift.protocol.TProtocol prot, Update struct) throws org.apache.thrift.TException {
+ TTupleProtocol iprot = (TTupleProtocol) prot;
+ BitSet incoming = iprot.readBitSet(7);
+ if (incoming.get(0)) {
+ struct.type = iprot.readI32();
+ struct.setTypeIsSet(true);
+ }
+ if (incoming.get(1)) {
+ struct.reserved = iprot.readI32();
+ struct.setReservedIsSet(true);
+ }
+ if (incoming.get(2)) {
+ struct.prefixlen = iprot.readI32();
+ struct.setPrefixlenIsSet(true);
+ }
+ if (incoming.get(3)) {
+ struct.label = iprot.readI32();
+ struct.setLabelIsSet(true);
+ }
+ if (incoming.get(4)) {
+ struct.rd = iprot.readString();
+ struct.setRdIsSet(true);
+ }
+ if (incoming.get(5)) {
+ struct.prefix = iprot.readString();
+ struct.setPrefixIsSet(true);
+ }
+ if (incoming.get(6)) {
+ struct.nexthop = iprot.readString();
+ struct.setNexthopIsSet(true);
+ }
+ }
+ }
+
+}
+
--- /dev/null
+/**
+ * Autogenerated by Thrift Compiler (0.9.1)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ * @generated
+ */
+
+package org.opendaylight.bgpmanager.thrift.gen;
+
+import java.util.Map;
+import java.util.HashMap;
+import org.apache.thrift.TEnum;
+
+public enum af_afi implements org.apache.thrift.TEnum {
+ AFI_IP(1);
+
+ private final int value;
+
+ private af_afi(int value) {
+ this.value = value;
+ }
+
+ /**
+ * Get the integer value of this enum value, as defined in the Thrift IDL.
+ */
+ public int getValue() {
+ return value;
+ }
+
+ /**
+ * Find a the enum type by its integer value, as defined in the Thrift IDL.
+ * @return null if the value is not found.
+ */
+ public static af_afi findByValue(int value) {
+ switch (value) {
+ case 1:
+ return AFI_IP;
+ default:
+ return null;
+ }
+ }
+}
--- /dev/null
+/**
+ * Autogenerated by Thrift Compiler (0.9.1)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ * @generated
+ */
+
+package org.opendaylight.bgpmanager.thrift.gen;
+
+import java.util.Map;
+import java.util.HashMap;
+import org.apache.thrift.TEnum;
+
+public enum af_safi implements org.apache.thrift.TEnum {
+ SAFI_IPV4_LABELED_UNICAST(4),
+ SAFI_MPLS_VPN(5);
+
+ private final int value;
+
+ private af_safi(int value) {
+ this.value = value;
+ }
+
+ /**
+ * Get the integer value of this enum value, as defined in the Thrift IDL.
+ */
+ public int getValue() {
+ return value;
+ }
+
+ /**
+ * Find a the enum type by its integer value, as defined in the Thrift IDL.
+ * @return null if the value is not found.
+ */
+ public static af_safi findByValue(int value) {
+ switch (value) {
+ case 4:
+ return SAFI_IPV4_LABELED_UNICAST;
+ case 5:
+ return SAFI_MPLS_VPN;
+ default:
+ return null;
+ }
+ }
+}
--- /dev/null
+/**
+ * Autogenerated by Thrift Compiler (0.9.1)
+ *
+ * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
+ * @generated
+ */
+
+package org.opendaylight.bgpmanager.thrift.gen;
+
+import org.apache.thrift.scheme.IScheme;
+import org.apache.thrift.scheme.SchemeFactory;
+import org.apache.thrift.scheme.StandardScheme;
+
+import org.apache.thrift.scheme.TupleScheme;
+import org.apache.thrift.protocol.TTupleProtocol;
+import org.apache.thrift.protocol.TProtocolException;
+import org.apache.thrift.EncodingUtils;
+import org.apache.thrift.TException;
+import org.apache.thrift.async.AsyncMethodCallback;
+import org.apache.thrift.server.AbstractNonblockingServer.*;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.EnumMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.EnumSet;
+import java.util.Collections;
+import java.util.BitSet;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class qbgpConstants {
+
+ public static final int LBL_NO_LABEL = 0;
+
+ public static final int LBL_EXPLICIT_NULL = 3;
+
+ public static final int BGP_RT_ADD = 0;
+
+ public static final int BGP_RT_DEL = 1;
+
+ public static final int GET_RTS_INIT = 0;
+
+ public static final int GET_RTS_NEXT = 1;
+
+ public static final int BGP_ERR_FAILED = 1;
+
+ public static final int BGP_ERR_ACTIVE = 10;
+
+ public static final int BGP_ERR_INACTIVE = 11;
+
+ public static final int BGP_ERR_NOT_ITER = 15;
+
+ public static final int BGP_ERR_PARAM = 100;
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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
+ */
+
+// the label argument in pushRoute can use these
+const i32 LBL_NO_LABEL = 0
+const i32 LBL_EXPLICIT_NULL = 3
+
+// FIB entry type
+const i32 BGP_RT_ADD = 0
+const i32 BGP_RT_DEL = 1
+
+// FIB table iteration op
+const i32 GET_RTS_INIT = 0
+const i32 GET_RTS_NEXT = 1
+
+/*
+ * Error codes.
+ * 0 is success.
+ * ERR_FAILED because something not permitted
+ * was attempted, such as deleting a route
+ * that doesn't exist.
+ * ERR_ACTIVE when session is sought to be created
+ * when it is already running.
+ * ERR_INACTIVE when an RPC is called but there is
+ * no session.
+ * ERR_NOT_ITER when GET_RTS_NEXT is called without
+ * initializing with GET_RTS_INIT
+ * ERR_PARAM when there is an issue with params
+ */
+
+const i32 BGP_ERR_FAILED = 1
+const i32 BGP_ERR_ACTIVE = 10
+const i32 BGP_ERR_INACTIVE = 11
+const i32 BGP_ERR_NOT_ITER = 15
+const i32 BGP_ERR_PARAM = 100
+
+// these are the supported afi-safi combinations
+enum af_afi {
+ AFI_IP = 1
+}
+
+enum af_safi {
+ SAFI_IPV4_LABELED_UNICAST = 4,
+ SAFI_MPLS_VPN = 5
+}
+
+/*
+ * FIB update.
+ * type is either RT_ADD(0) or RT_DEL(1)
+ */
+
+struct Update {
+ 1: i32 type,
+ 2: i32 reserved,
+ 3: i32 prefixlen,
+ 4: i32 label,
+ 5: string rd,
+ 6: string prefix,
+ 7: string nexthop
+}
+
+/*
+ * A sequence of FIB updates, valid only if errcode
+ is zero. Returned as a result of iteration using
+ getRoutes() (ie, a database read). more=0 signals
+ end of iteration.
+ */
+
+struct Routes {
+ 1: i32 errcode,
+ 2: optional list<Update> updates,
+ 4: optional i32 more
+}
+
+service BgpConfigurator {
+ /*
+ * startBgp() starts a BGP instance on the BGP VM. Graceful Restart
+ * also must be configured (stalepathTime > 0). If local BGP is
+ * restarting, announceFlush tells neighbor to flush all routes
+ * previously advertised by us. This is the F bit of RFC 4724.
+ */
+ i32 startBgp(1:i32 asNumber, 2:string routerId, 3: i32 port,
+ 4:i32 holdTime, 5:i32 keepAliveTime,
+ 6:i32 stalepathTime, 7:bool announceFlush),
+ i32 stopBgp(1:i32 asNumber),
+ i32 createPeer(1:string ipAddress, 2:i32 asNumber),
+ i32 deletePeer(1:string ipAddress)
+ i32 addVrf(1:string rd, 2:list<string> irts, 3:list<string> erts),
+ i32 delVrf(1:string rd),
+ /*
+ * pushRoute:
+ * IPv6 is not supported.
+ * 'nexthop' cannot be null for VPNv4 and LU.
+ * 'rd' is null for LU (and unicast).
+ * 'label' cannot be NO_LABEL for VPNv4 and LU.
+ * ipv4 unicast is not fully supported.
+ */
+ i32 pushRoute(1:string prefix, 2:string nexthop, 3:string rd, 4:i32 label),
+ /*
+ * withdrawRoute:
+ * Second argument is either 'rd' (VPNv4) or
+ * label (LU) as a string (eg: "2500")
+ */
+ i32 withdrawRoute(1:string prefix, 2:string rd),
+ i32 setEbgpMultihop(1:string peerIp, 2:i32 nHops),
+ i32 unsetEbgpMultihop(1:string peerIp),
+ i32 setUpdateSource(1:string peerIp, 2:string srcIp),
+ i32 unsetUpdateSource(1:string peerIp),
+ i32 enableAddressFamily(1:string peerIp, 2:af_afi afi, 3:af_safi safi),
+ i32 disableAddressFamily(1:string peerIp, 2:af_afi afi, 3:af_safi safi),
+ i32 setLogConfig(1:string logFileName, 2:string logLevel),
+ i32 enableGracefulRestart(1:i32 stalepathTime),
+ i32 disableGracefulRestart(),
+ /*
+ * getRoutes():
+ * optype is one of: GET_RTS_INIT: initialize iteration,
+ * GET_RTS_NEXT: get next bunch of routes. winSize is
+ * the size of the buffer that caller has allocated to
+ * receive the array. QBGP sends no more than the number
+ * of routes that would fit in this buffer, but not
+ * necessarily the maximum number that would fit.
+ * Calling INIT when NEXT is expected causes reinit.
+ */
+ Routes getRoutes(1:i32 optype, 2:i32 winSize)
+}
+
+service BgpUpdater {
+ oneway void onUpdatePushRoute(1:string rd, 2:string prefix,
+ 3:i32 prefixlen, 4:string nexthop,
+ 5:i32 label),
+ oneway void onUpdateWithdrawRoute(1:string rd, 2:string prefix,
+ 3:i32 prefixlen),
+ oneway void onStartConfigResyncNotification(),
+ /* communicate to ODL a BGP Notification received from peer */
+ oneway void onNotificationSendEvent(1:string prefix,
+ 2:byte errCode, 3:byte errSubcode)
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.bgpmanager.thrift.server;
+
+import java.util.*;
+
+import org.apache.thrift.server.TServer;
+import org.apache.thrift.server.TServer.Args;
+import org.apache.thrift.server.TSimpleServer;
+import org.apache.thrift.transport.TServerSocket;
+import org.apache.thrift.transport.TServerTransport;
+import org.opendaylight.bgpmanager.BgpManager;
+import org.opendaylight.bgpmanager.BgpConfigurationManager;
+import org.opendaylight.bgpmanager.FibDSWriter;
+import org.opendaylight.bgpmanager.thrift.gen.BgpUpdater;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTables;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BgpThriftService {
+ int ourPort;
+ BgpManager bgpManager;
+ FibDSWriter fibDSWriter;
+ TServer server;
+ // to store copy fo FIB-VRF tables on QBGP restart.
+ public List<VrfTables> stale_vrfTables;
+
+ private static final Logger LOGGER =
+ LoggerFactory.getLogger(BgpThriftService.class);
+
+ public BgpThriftService(int ourPort, BgpManager bm) {
+ this.ourPort = ourPort;
+ bgpManager = bm;
+ fibDSWriter = bm.getFibWriter();
+ }
+
+ public class BgpUpdateServer implements Runnable, BgpUpdater.Iface {
+
+ public void BgpUpdateServer() {
+ }
+
+ public void run() {
+ try {
+ BgpUpdater.Processor processor = new BgpUpdater.Processor(this);
+ TServerTransport transport = new TServerSocket(ourPort);
+ server = new TSimpleServer(new Args(transport).processor(processor));
+ server.serve();
+ } catch (Exception e) {
+ LOGGER.error("Exception in BGP Updater server"+e);
+ }
+ }
+
+ public void onUpdatePushRoute(String rd, String prefix, int plen,
+ String nexthop, int label) {
+ try {
+ BgpConfigurationManager.onUpdatePushRoute(rd, prefix, plen, nexthop, label);
+ } catch (Throwable e) {
+ LOGGER.error("failed to handle update route " ,e);
+ }
+ }
+
+ public void onUpdateWithdrawRoute(String rd, String prefix, int plen) {
+ LOGGER.debug("Route del ** {} ** {}/{} ", rd, prefix, plen);
+ try {
+ fibDSWriter.removeFibEntryFromDS(rd, prefix + "/" + plen);
+ } catch (Throwable e) {
+ LOGGER.error("failed to handle withdraw route " ,e);
+ }
+ }
+
+ public void onStartConfigResyncNotification() {
+ LOGGER.info("BGP (re)started");
+ try {
+ bgpManager.bgpRestarted();
+ } catch (Throwable e) {
+ LOGGER.error("failed to handle onStartConfigResyncNotification " ,e);
+ }
+ }
+
+ public void onNotificationSendEvent(String prefix, byte errCode,
+ byte errSubcode) {
+ int code = errCode;
+ int subCode = errSubcode;
+ bgpManager.sendNotificationEvent(prefix, errCode, errSubcode);
+ }
+
+ }
+
+ Thread thread;
+
+ public void start() {
+ thread = new Thread(new BgpUpdateServer());
+ thread.start();
+ }
+
+ public void stop() {
+ server.stop();
+ thread.stop();
+ }
+}
+
--- /dev/null
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgpmanager.impl.rev150326;
+
+import org.opendaylight.bgpmanager.BgpManager;
+
+public class BgpManagerImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgpmanager.impl.rev150326.AbstractBgpManagerImplModule {
+ public BgpManagerImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public BgpManagerImplModule(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.bgpmanager.impl.rev150326.BgpManagerImplModule 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() {
+ // TODO:implement
+ //throw new java.lang.UnsupportedOperationException();
+ BgpManager provider = new BgpManager();
+ //provider.setITMProvider(getItmDependency());
+ getBrokerDependency().registerProvider(provider);
+ return provider;
+ }
+
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: bgpmanager-impl yang module local name: bgpmanager-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Wed Mar 25 12:33:33 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.bgpmanager.impl.rev150326;
+public class BgpManagerImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgpmanager.impl.rev150326.AbstractBgpManagerImplModuleFactory {
+
+}
--- /dev/null
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+ <command>
+ <action class="org.opendaylight.bgpmanager.ConfigureBgpCli">
+ </action>
+ </command>
+ </command-bundle>
+
+<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+ <command>
+ <action class="org.opendaylight.bgpmanager.DisplayBgpConfigCli">
+ </action>
+ </command>
+</command-bundle>
+
+
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+ <command>
+ <action class="org.opendaylight.bgpmanager.VtyshCli"/>
+ </command>
+ </command-bundle>
+
+<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+ <command>
+ <action class="org.opendaylight.bgpmanager.commands.ClearBgpCli"/>
+ </command>
+ </command-bundle>
+
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+ <command>
+ <action class="org.opendaylight.bgpmanager.commands.Connect"/>
+ </command>
+ </command-bundle>
+
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+ <command>
+ <action class="org.opendaylight.bgpmanager.commands.Neighbor"/>
+ </command>
+ </command-bundle>
+
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+ <command>
+ <action class="org.opendaylight.bgpmanager.commands.Router"/>
+ </command>
+ </command-bundle>
+
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+ <command>
+ <action class="org.opendaylight.bgpmanager.commands.Vrf"/>
+ </command>
+ </command-bundle>
+
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+ <command>
+ <action class="org.opendaylight.bgpmanager.commands.Network"/>
+ </command>
+ </command-bundle>
+
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+ <command>
+ <action class="org.opendaylight.bgpmanager.commands.Misc"/>
+ </command>
+ </command-bundle>
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+ <command>
+ <action class="org.opendaylight.bgpmanager.commands.Cache"/>
+ </command>
+ </command-bundle>
+
+</blueprint>
--- /dev/null
+module bgpmanager-impl {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:bgpmanager:impl";
+ prefix "bgpmanager-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 bgpmanager-api { prefix bgpmgr-api; revision-date 2015-04-20;}
+ //import itm { prefix itm; revision-date 2015-07-01; }
+
+ description
+ "Service definition for bgpmanager project";
+
+ revision "2015-03-26" {
+ description
+ "Initial revision";
+ }
+
+ identity bgpmanager-impl {
+ base config:module-type;
+ config:provided-service bgpmgr-api:bgpmanager-api;
+ config:java-name-prefix BgpManagerImpl;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case bgpmanager-impl {
+ when "/config:modules/config:module/config:type = 'bgpmanager-impl'";
+ container broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true; //true or false
+ config:required-identity md-sal-binding:binding-broker-osgi-registry;
+ }
+ }
+ }
+ /*container itm {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity itm:itm;
+ }
+ }
+ }*/
+ }
+ }
+}
--- /dev/null
+package org.opendaylight.vpnservice.bgpmanager.test;
+
+import java.util.Collection;
+
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Preconditions;
+
+public abstract class AbstractMockFibManager<D extends DataObject> implements DataTreeChangeListener<D> {
+
+ public AbstractMockFibManager() {
+ // Do Nothing
+ }
+
+
+ public void onDataTreeChanged(Collection<DataTreeModification<D>> changes) {
+ // TODO Auto-generated method stub
+ }
+
+}
--- /dev/null
+package org.opendaylight.vpnservice.bgpmanager.test;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Collections;
+import java.util.concurrent.ExecutionException;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.bgpmanager.FibDSWriter;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(MockitoJUnitRunner.class)
+
+public class BgpManagerTest extends AbstractDataBrokerTest {
+ DataBroker dataBroker;
+ FibDSWriter bgpFibWriter = null ;
+ MockFibManager fibManager = null ;
+
+ @Before
+ public void setUp() throws Exception {
+ dataBroker = getDataBroker() ;
+ bgpFibWriter = new FibDSWriter(dataBroker);
+ fibManager = new MockFibManager(dataBroker);
+ }
+
+ @Test
+ public void testAddSinglePrefix() {
+ String rd = "101";
+ String prefix = "10.10.10.10/32";
+ String nexthop = "100.100.100.100";
+ int label = 1234;
+
+ bgpFibWriter.addFibEntryToDS(rd, prefix, nexthop, label);
+ assertEquals(1, fibManager.getDataChgCount());
+ }
+
+ @Test
+ public void testAddPrefixesInRd() {
+ String rd = "101";
+ String prefix = "10.10.10.10/32";
+ String nexthop = "100.100.100.100";
+ int label = 1234;
+
+ bgpFibWriter.addFibEntryToDS(rd, prefix, nexthop, label);
+ assertEquals(1, fibManager.getDataChgCount());
+
+ prefix = "10.10.10.11/32";
+ label = 3456;
+ bgpFibWriter.addFibEntryToDS(rd, prefix, nexthop, label);
+ assertEquals(2, fibManager.getDataChgCount());
+
+
+ }
+
+ @Test
+ public void testAddPrefixesAcrossRd() {
+ String rd = "101";
+ String prefix = "10.10.10.10/32";
+ String nexthop = "100.100.100.100";
+ int label = 1234;
+
+ bgpFibWriter.addFibEntryToDS(rd, prefix, nexthop, label);
+ assertEquals(1, fibManager.getDataChgCount());
+
+ rd = "102";
+ prefix = "10.10.10.11/32";
+ nexthop = "200.200.200.200";
+ label = 3456;
+ bgpFibWriter.addFibEntryToDS(rd, prefix, nexthop, label);
+ assertEquals(2, fibManager.getDataChgCount());
+
+ }
+
+
+ @Test
+ public void testRemovePrefix() {
+ String rd = "101";
+ String prefix = "10.10.10.10/32";
+ String nexthop = "100.100.100.100";
+ int label = 1234;
+
+ //add and then remove prefix
+ bgpFibWriter.addFibEntryToDS(rd, prefix, nexthop, label);
+ assertEquals(1, fibManager.getDataChgCount());
+ bgpFibWriter.removeFibEntryFromDS(rd, prefix);
+ assertEquals(0, fibManager.getDataChgCount());
+
+ }
+
+}
--- /dev/null
+package org.opendaylight.vpnservice.bgpmanager.test;
+
+import java.util.Collection;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.FibEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntry;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class MockFibManager extends AbstractMockFibManager<VrfEntry> {
+
+ private int nFibEntries = 0;
+
+ private ListenerRegistration<MockFibManager> listenerRegistration;
+
+ public MockFibManager( final DataBroker db) {
+ super() ;
+ registerListener(db) ;
+ }
+
+ private void registerListener(final DataBroker db) {
+ final DataTreeIdentifier<VrfEntry> treeId = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, getWildCardPath());
+ try {
+ listenerRegistration = db.registerDataTreeChangeListener(treeId, MockFibManager.this);
+ } catch (final Exception e) {
+ throw new IllegalStateException("FibManager registration Listener fail! System needs restart.", e);
+ }
+ }
+
+ private InstanceIdentifier<VrfEntry> getWildCardPath() {
+ return InstanceIdentifier.create(FibEntries.class).child(VrfTables.class).child(VrfEntry.class);
+ }
+
+ @Override
+ public void onDataTreeChanged(Collection<DataTreeModification<VrfEntry>> changes) {
+ for (DataTreeModification<VrfEntry> change : changes) {
+ final InstanceIdentifier<VrfEntry> key = change.getRootPath().getRootIdentifier();
+ final DataObjectModification<VrfEntry> mod = change.getRootNode();
+
+ switch (mod.getModificationType()) {
+ case DELETE:
+ nFibEntries -= 1;
+ break;
+ case WRITE:
+ if (mod.getDataBefore() == null) {
+ nFibEntries += 1;
+ } else {
+ // UPDATE COUNT UNCHANGED
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Unhandled modification type " + mod.getModificationType());
+ }
+ }
+ }
+
+ public int getDataChgCount() {
+ return nFibEntries;
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>bgpmanager</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <name>bgpmanager</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+
+ <modules>
+ <module>bgpmanager-api</module>
+ <module>bgpmanager-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>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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.mdsal</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>0.9.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <properties>
+ <vpnservices.version>0.3.0-SNAPSHOT</vpnservices.version>
+ <ietf.inet.types.version>2010.09.24.9-SNAPSHOT</ietf.inet.types.version>
+ <ietf.yang.types.version>2010.09.24.9-SNAPSHOT</ietf.yang.types.version>
+ <ietf.interfaces.version>2014.05.08.9-SNAPSHOT</ietf.interfaces.version>
+ <iana.if.type.version>2014.05.08.9-SNAPSHOT</iana.if.type.version>
+ <yang.ext.version>2013.09.07.9-SNAPSHOT</yang.ext.version>
+ <yangtools.version>1.0.0-SNAPSHOT</yangtools.version>
+ <mdsal.version>2.1.0-SNAPSHOT</mdsal.version>
+ <controller.mdsal.version>1.4.0-SNAPSHOT</controller.mdsal.version>
+ <vpns.mdsalutil.version>0.3.0-SNAPSHOT</vpns.mdsalutil.version>
+ <model.bgp.version>2013.07.15.9-SNAPSHOT</model.bgp.version>
+ </properties>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: --><!--
+Copyright (c) 2015 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.controller</groupId>
+ <artifactId>config-parent</artifactId>
+ <version>0.5.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>config-parent</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <properties>
+ <!-- ODL -->
+ <vpnservices.version>0.3.0-SNAPSHOT</vpnservices.version>
+ <yangtools.version>1.0.0-SNAPSHOT</yangtools.version>
+ <mdsal.model.version>0.9.0-SNAPSHOT</mdsal.model.version>
+ <controller.mdsal.version>1.4.0-SNAPSHOT</controller.mdsal.version>
+ <vpns.mdsalutil.version>0.3.0-SNAPSHOT</vpns.mdsalutil.version>
+ <model.bgp.version>2013.07.15.9-SNAPSHOT</model.bgp.version>
+ <openflowplugin.version>0.3.0-SNAPSHOT</openflowplugin.version>
+ <vpns.ovsdb.version>1.3.0-SNAPSHOT</vpns.ovsdb.version>
+ <liblldp.version>0.11.0-SNAPSHOT</liblldp.version>
+ <karaf.shell.console.version>3.0.3</karaf.shell.console.version>
+ <neutron.version>0.7.0-SNAPSHOT</neutron.version>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>mdsal-artifacts</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>mdsal-model-artifacts</artifactId>
+ <version>${mdsal.model.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <!-- Testing Dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>process-sources</phase>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <configLocation>
+ ${project.basedir}/../../commons/src/main/resources/vpns_checks.xml
+ </configLocation>
+ <failsOnError>true</failsOnError>
+ <includes>**/*.java,**/*.xml,**/*.ini,**/*.sh,**/*.bat</includes>
+ <excludes>**\/target\/,**\/bin\/,**\/third-party,**\/yang-gen-sal</excludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
--- /dev/null
+<?xml version="1.0"?>
+<!DOCTYPE module PUBLIC
+ "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
+ "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+
+<!--
+
+ Checkstyle configuration that checks the Google coding conventions from:
+
+ - Google Java Style
+ https://google-styleguide.googlecode.com/svn-history/r130/trunk/javaguide.html
+
+ Checkstyle is very configurable. Be sure to read the documentation at
+ http://checkstyle.sf.net (or in your downloaded distribution).
+
+ Most Checks are configurable, be sure to consult the documentation.
+
+ To completely disable a check, just comment it out or delete it from the file.
+
+ Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
+
+ -->
+
+<module name = "Checker">
+ <property name="charset" value="UTF-8"/>
+
+ <property name="severity" value="warning"/>
+
+ <!-- Checks for whitespace -->
+ <!-- See http://checkstyle.sf.net/config_whitespace.html -->
+ <module name="FileTabCharacter">
+ <property name="eachLine" value="true"/>
+ </module>
+
+ <module name="TreeWalker">
+ <module name="OuterTypeFilename"/>
+ <module name="IllegalTokenText">
+ <property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
+ <property name="format" value="\\u00(08|09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
+ <property name="message" value="Avoid using corresponding octal or Unicode escape."/>
+ </module>
+ <!-- Not yet supported https://jira.codehaus.org/browse/MCHECKSTYLE-261
+ <module name="AvoidEscapedUnicodeCharacters">
+ <property name="allowEscapesForControlCharacters" value="true"/>
+ <property name="allowByTailComment" value="true"/>
+ <property name="allowNonPrintableEscapes" value="true"/>
+ </module>
+ -->
+ <module name="LineLength">
+ <property name="max" value="120"/><!-- ODL projects use 120 max line length -->
+ <property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://"/>
+ </module>
+ <module name="AvoidStarImport"/>
+ <!-- Not yet supported https://jira.codehaus.org/browse/MCHECKSTYLE-261
+ <module name="OneTopLevelClass"/>
+ <module name="NoLineWrap"/>
+ -->
+ <module name="EmptyBlock">
+ <property name="option" value="TEXT"/>
+ <property name="tokens" value="LITERAL_TRY, LITERAL_CATCH, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
+ </module>
+ <module name="NeedBraces"/>
+ <module name="LeftCurly">
+ <property name="maxLineLength" value="100"/>
+ </module>
+ <module name="RightCurly"/>
+ <module name="RightCurly">
+ <property name="option" value="alone"/>
+ <property name="tokens" value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, LITERAL_DO, STATIC_INIT, INSTANCE_INIT"/>
+ </module>
+ <module name="WhitespaceAround">
+ <property name="allowEmptyConstructors" value="true"/>
+ <property name="allowEmptyMethods" value="true"/>
+ <!-- Not yet supported https://jira.codehaus.org/browse/MCHECKSTYLE-261
+ <property name="allowEmptyTypes" value="true"/>
+ <property name="allowEmptyLoops" value="true"/>
+ -->
+ <message key="ws.notFollowed"
+ value="WhitespaceAround: ''{0}'' is not followed by whitespace."/>
+ <message key="ws.notPreceded"
+ value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
+ </module>
+ <module name="OneStatementPerLine"/>
+ <module name="MultipleVariableDeclarations"/>
+ <module name="ArrayTypeStyle"/>
+ <module name="MissingSwitchDefault"/>
+ <module name="FallThrough"/>
+ <module name="UpperEll"/>
+ <module name="ModifierOrder"/>
+ <!-- Not yet supported https://jira.codehaus.org/browse/MCHECKSTYLE-261
+ <module name="EmptyLineSeparator">
+ <property name="allowNoEmptyLineBetweenFields" value="true"/>
+ </module>
+ <module name="SeparatorWrap">
+ <property name="tokens" value="DOT"/>
+ <property name="option" value="nl"/>
+ </module>
+ <module name="SeparatorWrap">
+ <property name="tokens" value="COMMA"/>
+ <property name="option" value="EOL"/>
+ </module>
+ -->
+ <module name="PackageName">
+ <property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
+ <message key="name.invalidPattern"
+ value="Package name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="TypeName">
+ <message key="name.invalidPattern"
+ value="Type name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="MemberName">
+ <property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
+ <message key="name.invalidPattern"
+ value="Member name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="ParameterName">
+ <property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
+ <message key="name.invalidPattern"
+ value="Parameter name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="LocalVariableName">
+ <property name="tokens" value="VARIABLE_DEF"/>
+ <property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
+ <!-- Not yet supported https://jira.codehaus.org/browse/MCHECKSTYLE-261
+ <property name="allowOneCharVarInForLoop" value="true"/>
+ -->
+ <message key="name.invalidPattern"
+ value="Local variable name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="ClassTypeParameterName">
+ <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
+ <message key="name.invalidPattern"
+ value="Class type name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="MethodTypeParameterName">
+ <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
+ <message key="name.invalidPattern"
+ value="Method type name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <module name="NoFinalizer"/>
+ <module name="GenericWhitespace">
+ <message key="ws.followed"
+ value="GenericWhitespace ''{0}'' is followed by whitespace."/>
+ <message key="ws.preceded"
+ value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
+ <message key="ws.illegalFollow"
+ value="GenericWhitespace ''{0}'' should followed by whitespace."/>
+ <message key="ws.notPreceded"
+ value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
+ </module>
+ <module name="Indentation">
+ <property name="basicOffset" value="4"/>
+ <property name="braceAdjustment" value="0"/>
+ <property name="caseIndent" value="4"/>
+ <property name="throwsIndent" value="4"/>
+ <!-- Not yet supported https://jira.codehaus.org/browse/MCHECKSTYLE-261
+ <property name="lineWrappingIndentation" value="4"/>
+ <property name="arrayInitIndent" value="2"/>
+ -->
+ </module>
+ <!-- Not yet supported https://jira.codehaus.org/browse/MCHECKSTYLE-261
+ <module name="AbbreviationAsWordInName">
+ <property name="ignoreFinal" value="false"/>
+ <property name="allowedAbbreviationLength" value="1"/>
+ </module>
+ <module name="OverloadMethodsDeclarationOrder"/>
+ <module name="VariableDeclarationUsageDistance"/>
+ <module name="CustomImportOrder">
+ <property name="thirdPartyPackageRegExp" value=".*"/>
+ <property name="specialImportsRegExp" value="com.google"/>
+ <property name="sortImportsInGroupAlphabetically" value="true"/>
+ <property name="customImportOrderRules" value="STATIC###SPECIAL_IMPORTS###THIRD_PARTY_PACKAGE###STANDARD_JAVA_PACKAGE"/>
+ </module>
+ -->
+ <module name="MethodParamPad"/>
+ <module name="OperatorWrap">
+ <property name="option" value="NL"/>
+ <property name="tokens" value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR "/>
+ </module>
+ <!-- Not yet supported https://jira.codehaus.org/browse/MCHECKSTYLE-261
+ <module name="AnnotationLocation">
+ <property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
+ </module>
+ <module name="AnnotationLocation">
+ <property name="tokens" value="VARIABLE_DEF"/>
+ <property name="allowSamelineMultipleAnnotations" value="true"/>
+ </module>
+ <module name="NonEmptyAtclauseDescription"/>
+ <module name="JavadocTagContinuationIndentation"/>
+ <module name="SummaryJavadocCheck">
+ <property name="forbiddenSummaryFragments" value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
+ </module>
+ <module name="JavadocParagraph"/>
+ <module name="AtclauseOrder">
+ <property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
+ <property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
+ </module>
+ -->
+ <module name="JavadocMethod">
+ <property name="scope" value="public"/>
+ <property name="allowMissingParamTags" value="true"/>
+ <property name="allowMissingThrowsTags" value="true"/>
+ <property name="allowMissingReturnTag" value="true"/>
+ <!-- Not yet supported https://jira.codehaus.org/browse/MCHECKSTYLE-261
+ <property name="minLineCount" value="2"/>
+ <property name="allowedAnnotations" value="Override, Test"/>
+ -->
+ <property name="allowThrowsTagsForSubclasses" value="true"/>
+ </module>
+ <module name="MethodName">
+ <property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
+ <message key="name.invalidPattern"
+ value="Method name ''{0}'' must match pattern ''{1}''."/>
+ </module>
+ <!-- Not yet supported https://jira.codehaus.org/browse/MCHECKSTYLE-261
+ <module name="SingleLineJavadoc"/>
+ -->
+ </module>
+</module>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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>binding-parent</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/binding-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>dhcpservice-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>iana-if-type-2014-05-08</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mdsalutil-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2015 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.dhcpservice.api;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.liblldp.BitBufferHelper;
+import org.opendaylight.controller.liblldp.BufferException;
+import org.opendaylight.controller.liblldp.HexEncode;
+import org.opendaylight.controller.liblldp.NetUtils;
+import org.opendaylight.controller.liblldp.Packet;
+import org.opendaylight.controller.liblldp.PacketException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.opendaylight.vpnservice.dhcpservice.api.DHCPConstants.*;
+
+public class DHCP extends Packet {
+ protected static final Logger logger = LoggerFactory
+ .getLogger(DHCP.class);
+ private static final String OP = "Op";
+ private static final String HTYPE = "Htype";
+ private static final String HLEN = "Hlen";
+ private static final String HOPS = "Hops";
+ private static final String XID = "Xid";
+ private static final String SECS = "Secs";
+ private static final String FLAGS = "Flags";
+ private static final String CIADDR = "Ciaddr";
+ private static final String YIADDR = "Yiaddr";
+ private static final String SIADDR = "Siaddr";
+ private static final String GIADDR = "Giaddr";
+ private static final String CHADDR = "Chaddr";
+ private static final String SNAME = "Sname";
+ private static final String FILE = "File";
+ private static final String MCOOKIE = "Mcookie";
+ private static final String OPTIONS = "Options";
+ private DHCPOptions dhcpOptions = null;
+
+ private static Map<String, Pair<Integer, Integer>> fieldCoordinates = new LinkedHashMap<String, Pair<Integer, Integer>>() {
+ private static final long serialVersionUID = 1L;
+ {
+ put(OP, new ImmutablePair<Integer, Integer>(0, 8));
+ put(HTYPE, new ImmutablePair<Integer, Integer>(8, 8));
+ put(HLEN, new ImmutablePair<Integer, Integer>(16, 8));
+ put(HOPS, new ImmutablePair<Integer, Integer>(24, 8));
+ put(XID, new ImmutablePair<Integer, Integer>(32, 32));
+ put(SECS, new ImmutablePair<Integer, Integer>(64, 16));
+ put(FLAGS, new ImmutablePair<Integer, Integer>(80, 16));
+ put(CIADDR, new ImmutablePair<Integer, Integer>(96, 32));
+ put(YIADDR, new ImmutablePair<Integer, Integer>(128, 32));
+ put(SIADDR, new ImmutablePair<Integer, Integer>(160, 32));
+ put(GIADDR, new ImmutablePair<Integer, Integer>(192, 32));
+ put(CHADDR, new ImmutablePair<Integer, Integer>(224, 128));
+ put(SNAME, new ImmutablePair<Integer, Integer>(352, 512));
+ put(FILE, new ImmutablePair<Integer, Integer>(864, 1024));
+ put(MCOOKIE, new ImmutablePair<Integer, Integer>(1888, 32));
+ put(OPTIONS, new ImmutablePair<Integer, Integer>(1920, 0));
+ }
+ };
+
+ private final Map<String, byte[]> fieldValues;
+
+ public DHCP() {
+ this(false);
+ }
+
+ public DHCP(boolean writeAccess) {
+ super(writeAccess);
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ corrupted = false;
+
+ setOp(BOOTREPLY);
+ setHtype(HTYPE_ETHER);
+ setHlen((byte)6);
+ setHops((byte)0);
+ setXid(0);
+ setSecs((short) 0);
+ setFlags((short) 0);
+ setCiaddr(0);
+ setYiaddr(0);
+ setSiaddr(0);
+ setGiaddr(0);
+ setChaddr(new byte[16]);
+ setSname(new byte[64]);
+ setFile(new byte[128]);
+ setMcookie(MAGIC_COOKIE);
+ setOptions(new byte[0]);
+ this.dhcpOptions = new DHCPOptions();
+ }
+
+ //Getters
+ public byte getOp() {
+ return (BitBufferHelper.getByte(fieldValues.get(OP)));
+ }
+
+ public byte getHtype() {
+ return (BitBufferHelper.getByte(fieldValues.get(HTYPE)));
+ }
+
+ public byte getHlen() {
+ return (BitBufferHelper.getByte(fieldValues.get(HLEN)));
+ }
+
+ public byte getHops() {
+ return (BitBufferHelper.getByte(fieldValues.get(HOPS)));
+ }
+
+ public int getXid() {
+ return (BitBufferHelper.getInt(fieldValues.get(XID)));
+ }
+
+ public short getSecs() {
+ return (BitBufferHelper.getShort(fieldValues.get(SECS)));
+ }
+
+ public short getFlags() {
+ return (BitBufferHelper.getShort(fieldValues.get(FLAGS)));
+ }
+
+ public byte[] getCiaddr() {
+ return fieldValues.get(CIADDR);
+ }
+
+ public byte[] getYiaddr() {
+ return fieldValues.get(YIADDR);
+ }
+
+
+ public byte[] getSiaddr() {
+ return fieldValues.get(SIADDR);
+ }
+
+ public InetAddress getSiaddrAsInetAddr() {
+ return DHCPUtils.byteArrayToInetAddr(fieldValues.get(SIADDR));
+ }
+
+ public byte[] getGiaddr() {
+ return fieldValues.get(GIADDR);
+ }
+
+ public byte[] getChaddr() {
+ return fieldValues.get(CHADDR);
+ }
+
+ public byte[] getSname() {
+ return fieldValues.get(SNAME);
+ }
+
+ public byte[] getFile() {
+ return fieldValues.get(FILE);
+ }
+
+ public int getMCookie() {
+ return (BitBufferHelper.getInt(fieldValues.get(MCOOKIE)));
+ }
+
+ public byte[] getOptions() {
+ return fieldValues.get(OPTIONS);
+ }
+
+// TODO:
+// public byte[] getPadding() {
+// return this.pad;
+// }
+
+ // Setters
+ @Override
+ public void setHeaderField(String headerField, byte[] readValue) {
+ if (headerField.equals(OPTIONS) &&
+ (readValue == null || readValue.length == 0)) {
+ hdrFieldsMap.remove(headerField);
+ return;
+ }
+ hdrFieldsMap.put(headerField, readValue);
+ }
+
+ public DHCP setOp(byte dhcpOp) {
+ byte[] op = BitBufferHelper.toByteArray(dhcpOp);
+ fieldValues.put(OP, op);
+ return this;
+ }
+
+ public DHCP setHtype(byte dhcpHtype) {
+ byte[] htype = BitBufferHelper.toByteArray(dhcpHtype);
+ fieldValues.put(HTYPE, htype);
+ return this;
+ }
+
+ public DHCP setHlen(byte dhcpHlen) {
+ byte[] hlen = BitBufferHelper.toByteArray(dhcpHlen);
+ fieldValues.put(HLEN, hlen);
+ return this;
+ }
+
+ public DHCP setHops(byte dhcpHops ) {
+ byte[] hops = BitBufferHelper.toByteArray(dhcpHops);
+ fieldValues.put(HOPS, hops);
+ return this;
+ }
+
+ public DHCP setXid(int dhcpXid ) {
+ byte[] xid = BitBufferHelper.toByteArray(dhcpXid);
+ fieldValues.put(XID, xid);
+ return this;
+ }
+
+ public DHCP setSecs(short dhcpSecs ) {
+ byte[] secs = BitBufferHelper.toByteArray(dhcpSecs);
+ fieldValues.put(SECS, secs);
+ return this;
+ }
+
+ public DHCP setFlags(short dhcpFlags ) {
+ byte[] flags = BitBufferHelper.toByteArray(dhcpFlags);
+ fieldValues.put(FLAGS, flags);
+ return this;
+ }
+
+ public DHCP setCiaddr(byte[] ciaddr) {
+ fieldValues.put(CIADDR, ciaddr);
+ return this;
+ }
+
+ public DHCP setCiaddr(int dhcpCiaddr ) {
+ byte[] ciaddr = BitBufferHelper.toByteArray(dhcpCiaddr);
+ fieldValues.put(CIADDR, ciaddr);
+ return this;
+ }
+
+ public DHCP setCiaddr(InetAddress dhcpCiaddr ) {
+ byte[] ciaddr = dhcpCiaddr.getAddress();
+ fieldValues.put(CIADDR, ciaddr);
+ return this;
+ }
+
+ public DHCP setCiaddr(String dhcpCiaddr) {
+ byte[] ciaddr = NetUtils.parseInetAddress(dhcpCiaddr).getAddress();
+ fieldValues.put(CIADDR, ciaddr);
+ return this;
+ }
+
+ public DHCP setYiaddr(byte[] yiaddr) {
+ fieldValues.put(YIADDR, yiaddr);
+ return this;
+ }
+
+ public DHCP setYiaddr(int dhcpYiaddr ) {
+ byte[] yiaddr = BitBufferHelper.toByteArray(dhcpYiaddr);
+ fieldValues.put(YIADDR, yiaddr);
+ return this;
+ }
+
+ public DHCP setYiaddr(InetAddress dhcpYiaddr ) {
+ byte[] yiaddr = dhcpYiaddr.getAddress();
+ fieldValues.put(YIADDR, yiaddr);
+ return this;
+ }
+
+ public DHCP setYiaddr(String dhcpYiaddr) {
+ byte[] yiaddr = NetUtils.parseInetAddress(dhcpYiaddr).getAddress();
+ fieldValues.put(YIADDR, yiaddr);
+ return this;
+ }
+
+ public DHCP setSiaddr(byte[] siaddr) {
+ fieldValues.put(SIADDR, siaddr);
+ return this;
+ }
+
+ public DHCP setSiaddr(int dhcpSiaddr ) {
+ byte[] siaddr = BitBufferHelper.toByteArray(dhcpSiaddr);
+ fieldValues.put(SIADDR, siaddr);
+ return this;
+ }
+
+ public DHCP setSiaddr(InetAddress dhcpSiaddr ) {
+ byte[] siaddr = dhcpSiaddr.getAddress();
+ fieldValues.put(SIADDR, siaddr);
+ return this;
+ }
+
+ public DHCP setSiaddr(String dhcpSiaddr) {
+ byte[] siaddr = NetUtils.parseInetAddress(dhcpSiaddr).getAddress();
+ fieldValues.put(SIADDR, siaddr);
+ return this;
+ }
+
+ public DHCP setGiaddr(byte[] giaddr) {
+ fieldValues.put(GIADDR, giaddr);
+ return this;
+ }
+
+ public DHCP setGiaddr(int dhcpGiaddr ) {
+ byte[] giaddr = BitBufferHelper.toByteArray(dhcpGiaddr);
+ fieldValues.put(GIADDR, giaddr);
+ return this;
+ }
+
+ public DHCP setGiaddr(InetAddress dhcpGiaddr ) {
+ byte[] giaddr = dhcpGiaddr.getAddress();
+ fieldValues.put(GIADDR, giaddr);
+ return this;
+ }
+
+ public DHCP setGiaddr(String dhcpGiaddr) {
+ byte[] giaddr = NetUtils.parseInetAddress(dhcpGiaddr).getAddress();
+ fieldValues.put(GIADDR, giaddr);
+ return this;
+ }
+
+ public DHCP setChaddr(byte[] chaddr) {
+ fieldValues.put(CHADDR, chaddr);
+ return this;
+ }
+
+ public DHCP setSname(byte[] sname) {
+ fieldValues.put(SNAME, sname);
+ return this;
+ }
+
+ public DHCP setFile(byte[] file) {
+ fieldValues.put(FILE, file);
+ return this;
+ }
+
+ public DHCP setMcookie(int dhcpMc ) {
+ byte[] mc = BitBufferHelper.toByteArray(dhcpMc);
+ fieldValues.put(MCOOKIE, mc);
+ return this;
+ }
+
+ public DHCP setOptions(byte[] options) {
+ fieldValues.put(OPTIONS, options);
+ return this;
+ }
+
+// public void setPadding(byte[] pad) {
+// this.pad = pad;
+// }
+
+ /**
+ * This method deserializes the data bits obtained from the wire into the
+ * respective header and payload which are of type Packet
+ *
+ * @param data byte[] data from wire to deserialize
+ * @param bitOffset int bit position where packet header starts in data
+ * array
+ * @param size int size of packet in bits
+ * @return Packet
+ * @throws PacketException
+ *
+ * Note: Copied from org.opendaylight.controller.sal.packet.Packet
+ */
+ @Override
+ public Packet deserialize(byte[] data, int bitOffset, int size)
+ throws PacketException {
+
+ // Deserialize the header fields one by one
+ int startOffset = 0, numBits = 0;
+ for (Entry<String, Pair<Integer, Integer>> pairs : hdrFieldCoordMap
+ .entrySet()) {
+ String hdrField = pairs.getKey();
+ startOffset = bitOffset + this.getfieldOffset(hdrField);
+ if(hdrField.equals(OPTIONS)) {
+ numBits = (size - DHCP_NOOPT_HDR_SIZE) * 8;
+ } else {
+ numBits = this.getfieldnumBits(hdrField);
+ }
+ byte[] hdrFieldBytes = null;
+ try {
+ hdrFieldBytes = BitBufferHelper.getBits(data, startOffset,
+ numBits);
+ } catch (BufferException e) {
+ throw new PacketException(e.getMessage());
+ }
+
+ /*
+ * Store the raw read value, checks the payload type and set the
+ * payloadClass accordingly
+ */
+ this.setHeaderField(hdrField, hdrFieldBytes);
+
+ if (logger.isTraceEnabled()) {
+ logger.trace("{}: {}: {} (offset {} bitsize {})",
+ new Object[] { this.getClass().getSimpleName(), hdrField,
+ HexEncode.bytesToHexString(hdrFieldBytes),
+ startOffset, numBits });
+ }
+ }
+
+ // Deserialize the payload now
+ int payloadStart = startOffset + numBits;
+ int payloadSize = data.length * NetUtils.NumBitsInAByte - payloadStart;
+
+ if (payloadClass != null) {
+ try {
+ payload = payloadClass.newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException(
+ "Error parsing payload for Ethernet packet", e);
+ }
+ payload.deserialize(data, payloadStart, payloadSize);
+ payload.setParent(this);
+ } else {
+ /*
+ * The payload class was not set, it means no class for parsing
+ * this payload is present. Let's store the raw payload if any.
+ */
+ int start = payloadStart / NetUtils.NumBitsInAByte;
+ int stop = start + payloadSize / NetUtils.NumBitsInAByte;
+ rawPayload = Arrays.copyOfRange(data, start, stop);
+ }
+ // Take care of computation that can be done only after deserialization
+ postDeserializeCustomOperation(data, payloadStart - getHeaderSize());
+
+ return this;
+ }
+
+ @Override
+ public byte[] serialize() throws PacketException {
+ this.setOptions(this.dhcpOptions.serialize());
+ byte[] data = super.serialize();
+ // Check for OPT_END at end of options
+ if (data.length > DHCP_MAX_SIZE) {
+ // shouldn't have happened
+ // Add exception?
+ logger.error("DHCP Packet too big");
+ } else if (data[data.length - 1] != (byte)255) {
+ // DHCP Options not ended properly
+ //throw new PacketException("Missing DHCP Option END");
+ logger.error("Missing DHCP Option END");
+ }else if(data.length < DHCP_MIN_SIZE) {
+ byte[] padding = new byte[DHCP_MIN_SIZE - data.length];
+ logger.debug("DHCP Pkt too small: {}, padding added {}",
+ data.length, padding.length);
+ data = ArrayUtils.addAll(data, padding);
+ }
+ return data;
+ }
+ @Override
+ /**
+ * Gets the number of bits for the fieldname specified
+ * If the fieldname has variable length like "Options", then this value is computed using the header length
+ * @param fieldname - String
+ * @return number of bits for fieldname - int
+ */
+ public int getfieldnumBits(String fieldName) {
+ if (fieldName.equals(OPTIONS)) {
+ byte[] barr = fieldValues.get(OPTIONS);
+ return (barr.length) * NetUtils.NumBitsInAByte;
+ }
+ return hdrFieldCoordMap.get(fieldName).getRight();
+ }
+
+ @Override
+ public int getHeaderSize() {
+ byte[] barr = fieldValues.get(OPTIONS);
+ int len = 0;
+ if(barr != null) { len = barr.length; }
+ return (DHCP_NOOPT_HDR_SIZE + len) * 8;
+ }
+
+
+ @Override
+ protected void postDeserializeCustomOperation(byte[] data, int startBitOffset) {
+ //TODO: Anything need to be done here?
+ // Check for MAGIC_COOKIE. This means we only support DHCP, not BOOTP
+ int cookie = BitBufferHelper.getInt(fieldValues.get(MCOOKIE));
+ if (cookie != MAGIC_COOKIE) {
+ logger.debug("Not DHCP packet");
+ // Throw exception?
+ }
+ // parse options into DHCPOptions
+ this.dhcpOptions.deserialize(this.getOptions());
+ // reset options byte array, this will also drop padding
+ this.setOptions(this.dhcpOptions.serialize());
+ }
+
+ // Set/get operations for Options
+ public void setMsgType(byte type) {
+ dhcpOptions.setOptionByte(OPT_MESSAGE_TYPE, type);
+ }
+
+ public byte getMsgType() {
+ return dhcpOptions.getOptionByte(OPT_MESSAGE_TYPE);
+ }
+
+ public void setOptionByte(byte code, byte opt) {
+ dhcpOptions.setOptionByte(code, opt);
+ }
+
+ public byte getOptionByte(byte code) {
+ return dhcpOptions.getOptionByte(code);
+ }
+
+ public void setOptionBytes(byte code, byte[] opt) {
+ dhcpOptions.setOption(code, opt);
+ }
+
+ public byte[] getOptionBytes(byte code) {
+ return dhcpOptions.getOptionBytes(code);
+ }
+
+ public void setOptionShort(byte code, short s) {
+ dhcpOptions.setOptionShort(code, s);
+ }
+
+ public short getOptionShort(byte code) {
+ return dhcpOptions.getOptionShort(code);
+ }
+
+ public void setOptionInt(byte code, int i) {
+ dhcpOptions.setOptionInt(code, i);
+ }
+
+ public int getOptionInt(byte code) {
+ return dhcpOptions.getOptionInt(code);
+ }
+
+ public void setOptionInetAddr(byte code, InetAddress addr) {
+ dhcpOptions.setOptionInetAddr(code, addr);
+ }
+
+ public InetAddress getOptionInetAddr(byte code) {
+ return dhcpOptions.getOptionInetAddr(code);
+ }
+
+ public void setOptionInetAddr(byte code, String addr) throws UnknownHostException {
+ dhcpOptions.setOptionStrAddr(code, addr);
+ }
+
+ public String getOptionStrAddr(byte code) {
+ return dhcpOptions.getOptionStrAddr(code);
+ }
+
+ public void setOptionStrAddrs(byte code, List<String> opt) throws UnknownHostException {
+ dhcpOptions.setOptionStrAddrs(code, opt);
+ }
+
+ public void setOptionString(byte code, String str) {
+ dhcpOptions.setOptionString(code, str);
+ }
+ public boolean containsOption(byte code) {
+ // TODO Auto-generated method stub
+ return dhcpOptions.containsOption(code);
+ }
+
+ public void unsetOption(byte code) {
+ dhcpOptions.unsetOption(code);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder ret = new StringBuilder();
+ ret.append(super.toString())
+ .append(dhcpOptions);
+
+ return ret.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.dhcpservice.api;
+
+public final class DHCPConstants {
+
+ // DHCP BOOTP CODES
+ public static final byte BOOTREQUEST = 1;
+ public static final byte BOOTREPLY = 2;
+
+ // DHCP HTYPE CODES
+ public static final byte HTYPE_ETHER = 1;
+
+ // DHCP MESSAGE CODES
+ public static final byte MSG_DISCOVER = 1;
+ public static final byte MSG_OFFER = 2;
+ public static final byte MSG_REQUEST = 3;
+ public static final byte MSG_DECLINE = 4;
+ public static final byte MSG_ACK = 5;
+ public static final byte MSG_NAK = 6;
+ public static final byte MSG_RELEASE = 7;
+ public static final byte MSG_INFORM = 8;
+ public static final byte MSG_FORCERENEW = 9;
+
+ // DHCP OPTIONS CODE
+ public static final byte OPT_PAD = 0;
+ public static final byte OPT_SUBNET_MASK = 1;
+ public static final byte OPT_TIME_OFFSET = 2;
+ public static final byte OPT_ROUTERS = 3;
+ public static final byte OPT_TIME_SERVERS = 4;
+ public static final byte OPT_NAME_SERVERS = 5;
+ public static final byte OPT_DOMAIN_NAME_SERVERS = 6;
+ public static final byte OPT_LOG_SERVERS = 7;
+ public static final byte OPT_COOKIE_SERVERS = 8;
+ public static final byte OPT_LPR_SERVERS = 9;
+ public static final byte OPT_IMPRESS_SERVERS = 10;
+ public static final byte OPT_RESOURCE_LOCATION_SERVERS = 11;
+ public static final byte OPT_HOST_NAME = 12;
+ public static final byte OPT_BOOT_SIZE = 13;
+ public static final byte OPT_MERIT_DUMP = 14;
+ public static final byte OPT_DOMAIN_NAME = 15;
+ public static final byte OPT_SWAP_SERVER = 16;
+ public static final byte OPT_ROOT_PATH = 17;
+ public static final byte OPT_EXTENSIONS_PATH = 18;
+ public static final byte OPT_IP_FORWARDING = 19;
+ public static final byte OPT_NON_LOCAL_SOURCE_ROUTING = 20;
+ public static final byte OPT_POLICY_FILTER = 21;
+ public static final byte OPT_MAX_DGRAM_REASSEMBLY = 22;
+ public static final byte OPT_DEFAULT_IP_TTL = 23;
+ public static final byte OPT_PATH_MTU_AGING_TIMEOUT = 24;
+ public static final byte OPT_PATH_MTU_PLATEAU_TABLE = 25;
+ public static final byte OPT_INTERFACE_MTU = 26;
+ public static final byte OPT_ALL_SUBNETS_LOCAL = 27;
+ public static final byte OPT_BROADCAST_ADDRESS = 28;
+ public static final byte OPT_PERFORM_MASK_DISCOVERY = 29;
+ public static final byte OPT_MASK_SUPPLIER = 30;
+ public static final byte OPT_ROUTER_DISCOVERY = 31;
+ public static final byte OPT_ROUTER_SOLICITATION_ADDRESS = 32;
+ public static final byte OPT_STATIC_ROUTES = 33;
+ public static final byte OPT_TRAILER_ENCAPSULATION = 34;
+ public static final byte OPT_ARP_CACHE_TIMEOUT = 35;
+ public static final byte OPT_IEEE802_3_ENCAPSULATION = 36;
+ public static final byte OPT_DEFAULT_TCP_TTL = 37;
+ public static final byte OPT_TCP_KEEPALIVE_INTERVAL = 38;
+ public static final byte OPT_TCP_KEEPALIVE_GARBAGE = 39;
+ public static final byte OPT_NIS_SERVERS = 41;
+ public static final byte OPT_NTP_SERVERS = 42;
+ public static final byte OPT_VENDOR_ENCAPSULATED_OPTIONS = 43;
+ public static final byte OPT_NETBIOS_NAME_SERVERS = 44;
+ public static final byte OPT_NETBIOS_DD_SERVER = 45;
+ public static final byte OPT_NETBIOS_NODE_TYPE = 46;
+ public static final byte OPT_NETBIOS_SCOPE = 47;
+ public static final byte OPT_FONT_SERVERS = 48;
+ public static final byte OPT_X_DISPLAY_MANAGER = 49;
+ public static final byte OPT_REQUESTED_ADDRESS = 50;
+ public static final byte OPT_LEASE_TIME = 51;
+ public static final byte OPT_OPTION_OVERLOAD = 52;
+ public static final byte OPT_MESSAGE_TYPE = 53;
+ public static final byte OPT_SERVER_IDENTIFIER = 54;
+ public static final byte OPT_PARAMETER_REQUEST_LIST = 55;
+ public static final byte OPT_MESSAGE = 56;
+ public static final byte OPT_MAX_MESSAGE_SIZE = 57;
+ public static final byte OPT_RENEWAL_TIME = 58;
+ public static final byte OPT_REBINDING_TIME = 59;
+ public static final byte OPT_VENDOR_CLASS_IDENTIFIER = 60;
+ public static final byte OPT_CLIENT_IDENTIFIER = 61;
+ public static final byte OPT_NWIP_DOMAIN_NAME = 62;
+ public static final byte OPT_NWIP_SUBOPTIONS = 63;
+ public static final byte OPT_NISPLUS_DOMAIN = 64;
+ public static final byte OPT_NISPLUS_SERVER = 65;
+ public static final byte OPT_TFTP_SERVER = 66;
+ public static final byte OPT_BOOTFILE = 67;
+ public static final byte OPT_MOBILE_IP_HOME_AGENT = 68;
+ public static final byte OPT_SMTP_SERVER = 69;
+ public static final byte OPT_POP3_SERVER = 70;
+ public static final byte OPT_NNTP_SERVER = 71;
+ public static final byte OPT_WWW_SERVER = 72;
+ public static final byte OPT_FINGER_SERVER = 73;
+ public static final byte OPT_IRC_SERVER = 74;
+ public static final byte OPT_STREETTALK_SERVER = 75;
+ public static final byte OPT_STDA_SERVER = 76;
+ public static final byte OPT_USER_CLASS = 77;
+ public static final byte OPT_FQDN = 81;
+ public static final byte OPT_AGENT_OPTIONS = 82;
+ public static final byte OPT_NDS_SERVERS = 85;
+ public static final byte OPT_NDS_TREE_NAME = 86;
+ public static final byte OPT_NDS_CONTEXT = 87;
+ public static final byte OPT_CLIENT_LAST_TRANSACTION_TIME = 91;
+ public static final byte OPT_ASSOCIATED_IP = 92;
+ public static final byte OPT_USER_AUTHENTICATION_PROTOCOL = 98;
+ public static final byte OPT_AUTO_CONFIGURE = 116;
+ public static final byte OPT_NAME_SERVICE_SEARCH = 117;
+ public static final byte OPT_SUBNET_SELECTION = 118;
+ public static final byte OPT_DOMAIN_SEARCH = 119;
+ public static final byte OPT_CLASSLESS_ROUTE = 121;
+ public static final byte OPT_END = -1;
+
+ public static final int MAGIC_COOKIE = 0x63825363;
+
+ public static final int DHCP_MIN_SIZE = 300;
+ public static final int DHCP_MAX_SIZE = 576;
+
+ public static final int DHCP_NOOPT_HDR_SIZE = 240;
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.dhcpservice.api;
+
+import java.math.BigInteger;
+
+public final class DHCPMConstants {
+
+ public static final long DHCP_TABLE_MAX_ENTRY = 10000;
+
+ public static final int DEFAULT_DHCP_FLOW_PRIORITY = 50;
+ public static final int ARP_FLOW_PRIORITY = 50;
+
+ public static final BigInteger COOKIE_DHCP_BASE = new BigInteger("6800000", 16);
+ public static final BigInteger METADATA_ALL_CLEAR_MASK = new BigInteger("0000000000000000", 16);
+ public static final BigInteger METADATA_ALL_SET_MASK = new BigInteger("FFFFFFFFFFFFFFFF", 16);
+
+ public static final String FLOWID_PREFIX = "DHCP.";
+ public static final String VMFLOWID_PREFIX = "DHCP.INTERFACE.";
+ public static final String BCAST_DEST_IP = "255.255.255.255";
+ public static final int BCAST_IP = 0xffffffff;
+
+ public static final short dhcpClientPort = 68;
+ public static final short dhcpServerPort = 67;
+
+ public static final int DEFAULT_LEASE_TIME = 86400;
+ public static final String DEFAULT_DOMAIN_NAME = "openstacklocal";
+
+ public static final BigInteger INVALID_DPID = new BigInteger("-1");
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.dhcpservice.api;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.LinkedHashMap;
+
+
+
+import java.util.List;
+
+import org.apache.commons.lang3.ArrayUtils;
+import org.opendaylight.controller.liblldp.HexEncode;
+import org.opendaylight.controller.liblldp.NetUtils;
+//import org.apache.commons.lang3.ArrayUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.opendaylight.vpnservice.dhcpservice.api.DHCPConstants.*;
+
+public class DHCPOptions {
+ protected static final Logger logger = LoggerFactory
+ .getLogger(DHCPOptions.class);
+
+ class DhcpOption extends Object {
+ private byte code;
+ private byte length;
+ private byte[] value;
+
+ public DhcpOption(byte code, byte[] value) {
+ if ((code != OPT_PAD) && (code != OPT_END) && (value != null)) {
+ this.code = code;
+ this.value = value;
+ this.length = (byte) value.length;
+ }
+ }
+
+ public byte getCode() {
+ return this.code;
+ }
+
+ public byte[] getValue() {
+ return this.value;
+ }
+
+ public byte[] serialize() {
+ byte[] opt1 = new byte[2];
+ opt1[0] = this.code;
+ opt1[1] = this.length;
+ return ArrayUtils.addAll(opt1, this.value);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("{ ")
+ .append("code: ").append(this.code)
+ .append(", len: ").append(this.length)
+ .append(", value: 0x").append(HexEncode.bytesToHexString(this.value))
+ .append(" }");
+ return sb.toString();
+ }
+ }
+
+ private LinkedHashMap<Byte, DhcpOption> options;
+
+ public DHCPOptions() {
+ options = new LinkedHashMap<Byte, DhcpOption>();
+ }
+
+ private void setOption(DhcpOption opt) {
+ this.options.put(opt.getCode(), opt);
+ }
+
+ private DhcpOption getOption(byte code) {
+ return this.options.get(code);
+ }
+
+ public void setOption(byte code, byte[] opt) {
+ this.setOption(new DhcpOption(code, opt));
+ }
+
+ public byte[] getOptionBytes(byte code) {
+ try{
+ return this.getOption(code).getValue();
+ }
+ catch (NullPointerException e)
+ {
+ return null;
+ }
+ }
+
+ public void setOptionByte(byte code, byte opt) {
+ this.setOption(new DhcpOption(code, DHCPUtils.byteToByteArray(opt)));
+ }
+
+ public byte getOptionByte(byte code) {
+ return this.getOption(code).getValue()[0];
+ }
+
+ public void setOptionShort(byte code, short opt) {
+ this.setOption(new DhcpOption(code, DHCPUtils.shortToByteArray(opt)));
+ }
+
+ public short getOptionShort(byte code) {
+ byte[] opt = this.getOptionBytes(code);
+ return DHCPUtils.byteArrayToShort(opt);
+ }
+
+ public void setOptionInt(byte code, int opt) {
+ this.setOption(new DhcpOption(code, DHCPUtils.intToByteArray(opt)));
+ }
+
+ public int getOptionInt(byte code) {
+ byte[] opt = this.getOptionBytes(code);
+ return NetUtils.byteArray4ToInt(opt);
+ }
+
+ public void setOptionInetAddr(byte code, InetAddress opt) {
+ this.setOption(new DhcpOption(code, DHCPUtils.inetAddrToByteArray(opt)));
+ }
+
+ public InetAddress getOptionInetAddr(byte code) {
+ byte[] opt = this.getOptionBytes(code);
+ try {
+ return InetAddress.getByAddress(opt);
+ } catch (UnknownHostException | NullPointerException e) {
+ return null;
+ }
+ }
+
+ public void setOptionStrAddr(byte code, String opt) throws UnknownHostException {
+ this.setOption(new DhcpOption(code, DHCPUtils.strAddrToByteArray(opt)));
+ }
+
+ public String getOptionStrAddr(byte code) {
+ byte[] opt = this.getOptionBytes(code);
+ try {
+ return InetAddress.getByAddress(opt).getHostAddress();
+ } catch (UnknownHostException| NullPointerException e) {
+ return null;
+ }
+ }
+
+ public void setOptionStrAddrs(byte code, List<String> addrs) throws UnknownHostException {
+ if(!addrs.isEmpty()) {
+ this.setOption(new DhcpOption(code, DHCPUtils.strListAddrsToByteArray(addrs)));
+ }
+ }
+
+ public void setOptionString(byte code, String str) {
+ this.setOption(new DhcpOption(code, str.getBytes()));
+ }
+
+ public byte[] serialize() {
+ byte[] options = new byte[0];
+ for(DhcpOption dOpt: this.options.values()) {
+ options = ArrayUtils.addAll(options, dOpt.serialize());
+ }
+ byte[] end = new byte[] {(byte)255};
+ options = ArrayUtils.addAll(options, end);
+ return options;
+ }
+
+ private byte[] getOptionValArray(byte[] opt, int pos, int len) {
+ byte[] val = new byte[len];
+ for(int i = 0; i < len; i++) {
+ val[i] = opt[pos + i];
+ }
+ return val;
+ }
+
+ public void deserialize(byte[] options) {
+ int pos = 0;
+ byte code, len;
+ byte[] value;
+ if (options != null) {
+ while (pos < options.length) {
+ code = options[pos++];
+ if (code == OPT_END) {
+ break;
+ }
+ len = options[pos++];
+ if ((len + pos) > options.length) {
+ // Throw exception???
+ break;
+ }
+ value = getOptionValArray(options, pos, len);
+ setOption(code, value);
+ pos += len;
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("{");
+ int i = 1;
+ for(DhcpOption dOpt: this.options.values()) {
+ //options = ArrayUtils.addAll(options, dOpt.serialize());
+ sb.append("Option").append(i++)
+ .append(dOpt.toString());
+ }
+ sb.append("}");
+ return sb.toString();
+ }
+
+ public boolean containsOption(byte code) {
+ return options.containsKey(code);
+ }
+
+ public DhcpOption unsetOption(byte code) {
+ return options.remove(code);
+ }
+
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.dhcpservice.api;
+
+
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+
+public abstract class DHCPUtils {
+
+ public static byte[] byteToByteArray(byte b) {
+ return new byte[] {b};
+ }
+
+ public static byte[] shortToByteArray(short s) {
+ return new byte[] { (byte) ((s >> 8) & 0xff), (byte) (s & 0xff) };
+ }
+
+ public static byte[] intToByteArray(int i ) {
+ return new byte[] { (byte) ((i >> 24) & 0xff), (byte) ((i >> 16) & 0xff), (byte) ((i >> 8) & 0xff),
+ (byte) (i & 0xff) };
+ }
+
+ public static byte[] inetAddrToByteArray(InetAddress a) {
+ return a.getAddress();
+ }
+
+ public static byte[] strAddrToByteArray(String addr) {
+ try {
+ return InetAddress.getByName(addr).getAddress();
+ } catch (UnknownHostException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ public static byte[] strListAddrsToByteArray(List<String> strList) {
+ byte[] result = new byte[strList.size() * 4];
+ byte[] addr = new byte[4];
+ try {
+ for (int i = 0; i < strList.size(); i++) {
+ addr = InetAddress.getByName(strList.get(i)).getAddress();
+ System.arraycopy(addr, 0, result, i*4, 4);
+ }
+ } catch (UnknownHostException e) {
+ return null;
+ }
+ return result;
+ }
+
+ public static short byteArrayToShort(byte[] ba) {
+ if (ba == null || ba.length != 2) {
+ return 0;
+ }
+ return (short) ((0xff & ba[0]) << 8 | (0xff & ba[1]));
+ }
+
+ public static InetAddress byteArrayToInetAddr(byte[] ba) {
+ try {
+ return InetAddress.getByAddress(ba);
+ } catch (UnknownHostException e) {
+ return null;
+ }
+ }
+
+ public static byte[] strMacAddrtoByteArray(String macAddress) {
+ if(macAddress == null) {
+ return null;
+ }
+ String[] bytes = macAddress.split(":");
+ byte[] result = new byte[bytes.length];
+ for (int i = 0; i < bytes.length; i++) {
+ BigInteger temp = new BigInteger(bytes[i], 16);
+ byte[] raw = temp.toByteArray();
+ result[i] = raw[raw.length - 1];
+ }
+ return result;
+ }
+
+ public static String byteArrayToString(byte[] bytes) {
+ StringBuilder str = new StringBuilder();
+ for (byte b : bytes) {
+ str.append(Integer.toHexString((b >>> 4) & 0x0F));
+ str.append(Integer.toHexString(b & 0x0F));
+ str.append(":");
+ }
+ str.deleteCharAt(str.lastIndexOf(":"));
+ return str.toString();
+ }
+}
--- /dev/null
+module vpnservice-dhcp {
+ namespace "urn:opendaylight:vpnservice:dhcp";
+ prefix "dhcp";
+
+ import ietf-inet-types {
+ prefix inet;
+ revision-date "2010-09-24";
+ }
+
+ revision "2016-04-28" {
+ description "It provides required datastore containers to handle DHCP requests
+ coming from access or external tunnel ports";
+ }
+
+ container designated-switches-for-external-tunnels {
+ config true;
+ description "contains designated dataplane-node-identifier which handles DHCP requests for each external tunnel";
+ list designated-switch-for-tunnel {
+ key "tunnel-remote-ip-address elan-instance-name";
+ leaf tunnel-remote-ip-address {
+ description "remote end point ip address of external tunnel";
+ type inet:ip-address;
+ }
+ leaf elan-instance-name {
+ description "elan name indicates l2 network domain";
+ type string;
+ }
+ leaf dpId {
+ description "contains dataplane-node-identifier";
+ type int64;
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+module dhcpservice-api {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:dhcpservice:api";
+ prefix "dhcpservice-api";
+
+ revision "2015-07-10" {
+ description
+ "Initial revision for DHCP Service module";
+ }
+
+ container interface-name-mac-addresses {
+ config false;
+ description
+ "Container to hold list of interface names and MAC address";
+
+ list interface-name-mac-address {
+ max-elements "unbounded";
+ min-elements "0";
+ key "interface-name";
+ description
+ "Specifies the name of the interface";
+
+ leaf interface-name {
+ type string;
+ description
+ "The name of the interface.";
+ }
+
+ leaf mac-address {
+ type string;
+ description
+ "The VM mac address for the interface.";
+ }
+ }
+ }
+}
\ 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) 2015 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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>dhcpservice-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>dhcpservice-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.model</groupId>
+ <artifactId>model-flow-service</artifactId>
+ <version>${openflowplugin.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mdsalutil-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>neutronvpn-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.console</artifactId>
+ <version>${karaf.shell.console.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.neutron</groupId>
+ <artifactId>model</artifactId>
+ <version>${neutron.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-net</groupId>
+ <artifactId>commons-net</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>interfacemgr-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>elanmanager-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.ovsdb</groupId>
+ <artifactId>hwvtepsouthbound-api</artifactId>
+ <version>${vpns.ovsdb.version}</version>
+ </dependency>
+ </dependencies>
+
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright (c) 2015 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:dhcpservice:impl?module=dhcpservice-impl&revision=2015-07-10</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:mdsalutil:api?module=odl-mdsalutil&revision=2015-04-10</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:config:distributed-entity-ownership-service?module=distributed-entity-ownership-service&revision=2015-08-10</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:neutronvpn:api?module=neutronvpn-api&revision=2015-08-12</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:dhcpservice:impl">prefix:dhcpservice-impl</type>
+ <name>dhcpservice-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>
+ <notification-service>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-notification-service</type>
+ <name>binding-notification-broker</name>
+ </notification-service>
+ <mdsalutil>
+ <type xmlns:mdsalutil="urn:opendaylight:params:xml:ns:yang:mdsalutil:api">mdsalutil:odl-mdsalutil</type>
+ <name>mdsalutil-service</name>
+ </mdsalutil>
+ <neutronvpn>
+ <type xmlns:neutronvpn="urn:opendaylight:params:xml:ns:yang:neutronvpn:api">neutronvpn:neutronvpn-api</type>
+ <name>neutronvpn</name>
+ </neutronvpn>
+ <entity-ownership-service>
+ <type xmlns:entity-ownership="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:entity-ownership-service">entity-ownership:entity-ownership-service</type>
+ <name>entity-ownership-service</name>
+ </entity-ownership-service>
+ </module>
+ </modules>
+ </data>
+ </configuration>
+</snapshot>
--- /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.dhcpservice;
+
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
+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.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.datastoreutils.AsyncClusteredDataChangeListenerBase;
+import org.opendaylight.vpnservice.dhcpservice.api.DHCPMConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.DhcpConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.dhcp.config.Configs;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DhcpConfigListener extends AsyncClusteredDataChangeListenerBase<DhcpConfig, DhcpConfigListener> implements AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DhcpConfigListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private DhcpManager dhcpManager;
+
+ public DhcpConfigListener(final DataBroker db, final DhcpManager dhcpMgr) {
+ super(DhcpConfig.class, DhcpConfigListener.class);
+ dhcpManager = dhcpMgr;
+ registerListener(db);
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ getWildCardPath(), DhcpConfigListener.this, AsyncDataBroker.DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("NodeListener: DataChange listener registration fail!", e);
+ throw new IllegalStateException("NodeListener: registration Listener failed.", e);
+ }
+ }
+
+ protected InstanceIdentifier<DhcpConfig> getWildCardPath() {
+ return InstanceIdentifier.create(DhcpConfig.class);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DhcpConfigListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.debug("DhcpConfig Listener Closed");
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<DhcpConfig> identifier, DhcpConfig del) {
+ LOG.trace("DhcpConfig removed: {}", del);
+ updateConfig(null);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<DhcpConfig> identifier, DhcpConfig original, DhcpConfig update) {
+ LOG.trace("DhcpConfig changed to {}", update);
+ updateConfig(update);
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<DhcpConfig> identifier, DhcpConfig add) {
+ LOG.trace("DhcpConfig added {}", add);
+ updateConfig(add);
+ }
+
+ private void updateConfig(DhcpConfig update) {
+ //TODO: Update operational with actual values
+ if(update == null || update.getConfigs() == null || update.getConfigs().isEmpty()) {
+ dhcpManager.setLeaseDuration(DHCPMConstants.DEFAULT_LEASE_TIME);
+ dhcpManager.setDefaultDomain(DHCPMConstants.DEFAULT_DOMAIN_NAME);
+ return;
+ }
+ Configs config = update.getConfigs().get(0);
+ if(config.getLeaseDuration() != null) {
+ dhcpManager.setLeaseDuration(config.getLeaseDuration());
+ }
+ if(config.getDefaultDomain() != null) {
+ dhcpManager.setDefaultDomain(config.getDefaultDomain());
+ //TODO: What to do if string is ""
+ }
+ }
+
+ @Override
+ protected ClusteredDataChangeListener getDataChangeListener() {
+ return DhcpConfigListener.this;
+ }
+
+ @Override
+ protected DataChangeScope getDataChangeScope() {
+ return AsyncDataBroker.DataChangeScope.BASE;
+ }
+}
--- /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.dhcpservice;
+
+import java.math.BigInteger;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
+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.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.vpnservice.datastoreutils.AsyncClusteredDataChangeListenerBase;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.dhcp.rev160428.DesignatedSwitchesForExternalTunnels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.dhcp.rev160428.designated.switches._for.external.tunnels.DesignatedSwitchForTunnel;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DhcpDesignatedDpnListener extends AsyncClusteredDataChangeListenerBase<DesignatedSwitchForTunnel, DhcpDesignatedDpnListener> implements AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DhcpDesignatedDpnListener.class);
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private DhcpExternalTunnelManager dhcpExternalTunnelManager;
+ private DataBroker broker;
+
+ public DhcpDesignatedDpnListener(final DhcpExternalTunnelManager dhcpExternalTunnelManager, final DataBroker broker) {
+ super(DesignatedSwitchForTunnel.class, DhcpDesignatedDpnListener.class);
+ this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
+ this.broker = broker;
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DhcpDesignatedDpnListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.debug("DhcpDesignatedDpnListener Listener Closed");
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<DesignatedSwitchForTunnel> identifier, DesignatedSwitchForTunnel del) {
+ dhcpExternalTunnelManager.removeFromLocalCache(BigInteger.valueOf(del.getDpId()), del.getTunnelRemoteIpAddress(), del.getElanInstanceName());
+ dhcpExternalTunnelManager.unInstallDhcpFlowsForVms(del.getElanInstanceName(), del.getTunnelRemoteIpAddress(), DhcpServiceUtils.getListOfDpns(broker));
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<DesignatedSwitchForTunnel> identifier, DesignatedSwitchForTunnel original,
+ DesignatedSwitchForTunnel update) {
+ BigInteger designatedDpnId = BigInteger.valueOf(update.getDpId());
+ IpAddress tunnelRemoteIpAddress = update.getTunnelRemoteIpAddress();
+ String elanInstanceName = update.getElanInstanceName();
+ dhcpExternalTunnelManager.removeFromLocalCache(BigInteger.valueOf(original.getDpId()), original.getTunnelRemoteIpAddress(), original.getElanInstanceName());
+ dhcpExternalTunnelManager.updateLocalCache(designatedDpnId, tunnelRemoteIpAddress, elanInstanceName);
+ List<BigInteger> elanDpns = DhcpServiceUtils.getDpnsForElan(elanInstanceName, broker);
+ if (elanDpns == null || elanDpns.isEmpty()) {
+ dhcpExternalTunnelManager.installRemoteMcastMac(designatedDpnId, tunnelRemoteIpAddress, elanInstanceName);
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<DesignatedSwitchForTunnel> identifier, DesignatedSwitchForTunnel add) {
+ BigInteger designatedDpnId = BigInteger.valueOf(add.getDpId());
+ IpAddress tunnelRemoteIpAddress = add.getTunnelRemoteIpAddress();
+ String elanInstanceName = add.getElanInstanceName();
+ dhcpExternalTunnelManager.updateLocalCache(designatedDpnId, tunnelRemoteIpAddress, elanInstanceName);
+ List<BigInteger> elanDpns = DhcpServiceUtils.getDpnsForElan(elanInstanceName, broker);
+ if (elanDpns == null || elanDpns.isEmpty()) {
+ dhcpExternalTunnelManager.installRemoteMcastMac(designatedDpnId, tunnelRemoteIpAddress, elanInstanceName);
+ }
+ }
+
+ @Override
+ protected InstanceIdentifier<DesignatedSwitchForTunnel> getWildCardPath() {
+ return InstanceIdentifier.create(DesignatedSwitchesForExternalTunnels.class).child(DesignatedSwitchForTunnel.class);
+ }
+
+ @Override
+ protected ClusteredDataChangeListener getDataChangeListener() {
+ return DhcpDesignatedDpnListener.this;
+ }
+
+ @Override
+ protected DataChangeScope getDataChangeScope() {
+ return AsyncDataBroker.DataChangeScope.SUBTREE;
+ }
+}
--- /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.dhcpservice;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.dhcpservice.api.DHCPMConstants;
+import org.opendaylight.vpnservice.mdsalutil.MDSALDataStoreUtils;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.utils.L2GatewayCacheUtils;
+import org.opendaylight.vpnservice.neutronvpn.api.utils.NeutronUtils;
+import org.opendaylight.vpnservice.utils.clustering.ClusteringUtils;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepSouthboundConstants;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepSouthboundUtils;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepUtils;
+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.state.Interface.OperStatus;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.dhcp.rev160428.DesignatedSwitchesForExternalTunnels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.dhcp.rev160428.designated.switches._for.external.tunnels.DesignatedSwitchForTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.dhcp.rev160428.designated.switches._for.external.tunnels.DesignatedSwitchForTunnelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.dhcp.rev160428.designated.switches._for.external.tunnels.DesignatedSwitchForTunnelKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class DhcpExternalTunnelManager {
+
+ private static final Logger logger = LoggerFactory.getLogger(DhcpExternalTunnelManager.class);
+ public static final String UNKNOWN_DMAC = "00:00:00:00:00:00";
+ private static final FutureCallback<Void> DEFAULT_CALLBACK =
+ new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(Void result) {
+ logger.debug("Success in Datastore write operation");
+ }
+ @Override
+ public void onFailure(Throwable error) {
+ logger.error("Error in Datastore write operation", error);
+ };
+ };
+ private final DataBroker broker;
+ private IMdsalApiManager mdsalUtil;
+
+ private ConcurrentMap<BigInteger, List<Pair<IpAddress, String>>> designatedDpnsToTunnelIpElanNameCache = new ConcurrentHashMap<BigInteger, List<Pair<IpAddress, String>>>();
+ private ConcurrentMap<Pair<IpAddress, String>, Set<String>> tunnelIpElanNameToVmMacCache = new ConcurrentHashMap<Pair<IpAddress, String>, Set<String>>();
+ private ConcurrentMap<Pair<BigInteger, String>, Port> vniMacAddressToPortCache = new ConcurrentHashMap<Pair<BigInteger, String>, Port>();
+ private ItmRpcService itmRpcService;
+ private EntityOwnershipService entityOwnershipService;
+
+ public DhcpExternalTunnelManager(DataBroker broker, IMdsalApiManager mdsalUtil, ItmRpcService itmRpcService, EntityOwnershipService entityOwnershipService) {
+ this.broker = broker;
+ this.mdsalUtil = mdsalUtil;
+ this.itmRpcService = itmRpcService;
+ this.entityOwnershipService = entityOwnershipService;
+ initilizeCaches();
+ }
+
+ private void initilizeCaches() {
+ logger.trace("Loading designatedDpnsToTunnelIpElanNameCache");
+ InstanceIdentifier<DesignatedSwitchesForExternalTunnels> instanceIdentifier = InstanceIdentifier.builder(DesignatedSwitchesForExternalTunnels.class).build();
+ Optional<DesignatedSwitchesForExternalTunnels> designatedSwitchForTunnelOptional = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, instanceIdentifier);
+ if (designatedSwitchForTunnelOptional.isPresent()) {
+ List<DesignatedSwitchForTunnel> list = designatedSwitchForTunnelOptional.get().getDesignatedSwitchForTunnel();
+ for (DesignatedSwitchForTunnel designatedSwitchForTunnel : list) {
+ List<Pair<IpAddress, String>> listOfTunnelIpElanNamePair = designatedDpnsToTunnelIpElanNameCache.get(designatedSwitchForTunnel.getDpId());
+ if (listOfTunnelIpElanNamePair == null) {
+ listOfTunnelIpElanNamePair = new LinkedList<Pair<IpAddress, String>>();
+ }
+ Pair<IpAddress, String> tunnelIpElanNamePair = new ImmutablePair<IpAddress, String>(designatedSwitchForTunnel.getTunnelRemoteIpAddress(), designatedSwitchForTunnel.getElanInstanceName());
+ listOfTunnelIpElanNamePair.add(tunnelIpElanNamePair);
+ designatedDpnsToTunnelIpElanNameCache.put(BigInteger.valueOf(designatedSwitchForTunnel.getDpId()), listOfTunnelIpElanNamePair);
+ }
+ }
+ logger.trace("Loading vniMacAddressToPortCache");
+ InstanceIdentifier<Ports> inst = InstanceIdentifier.builder(Neutron.class).child(Ports.class).build();
+ Optional<Ports> optionalPorts = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, inst);
+ if (optionalPorts.isPresent()) {
+ List<Port> list = optionalPorts.get().getPort();
+ for (Port port : list) {
+ if(NeutronUtils.isPortVnicTypeNormal(port)) {
+ continue;
+ }
+ String macAddress = port.getMacAddress();
+ Uuid networkId = port.getNetworkId();
+ String segmentationId = DhcpServiceUtils.getSegmentationId(networkId, broker);
+ if (segmentationId == null) {
+ return;
+ }
+ updateVniMacToPortCache(new BigInteger(segmentationId), macAddress, port);
+ }
+ }
+
+ }
+
+
+ public BigInteger designateDpnId(IpAddress tunnelIp,
+ String elanInstanceName, List<BigInteger> dpns) {
+ BigInteger designatedDpnId = readDesignatedSwitchesForExternalTunnel(tunnelIp, elanInstanceName);
+ if (designatedDpnId != null && !designatedDpnId.equals(DHCPMConstants.INVALID_DPID)) {
+ logger.trace("Dpn {} already designated for tunnelIp - elan : {} - {}", designatedDpnId, tunnelIp, elanInstanceName);
+ return designatedDpnId;
+ }
+ return chooseDpn(tunnelIp, elanInstanceName, dpns);
+ }
+
+ public void installDhcpFlowsForVms(IpAddress tunnelIp, String elanInstanceName, List<BigInteger> dpns,
+ BigInteger designatedDpnId, String vmMacAddress) {
+ installDhcpEntries(designatedDpnId, vmMacAddress, entityOwnershipService);
+ dpns.remove(designatedDpnId);
+ for (BigInteger dpn : dpns) {
+ installDhcpDropAction(dpn, vmMacAddress, entityOwnershipService);
+ }
+ updateLocalCache(tunnelIp, elanInstanceName, vmMacAddress);
+ }
+
+ public void installDhcpFlowsForVms(IpAddress tunnelIp,
+ String elanInstanceName, BigInteger designatedDpnId, Set<String> listVmMacAddress) {
+ for (String vmMacAddress : listVmMacAddress) {
+ installDhcpEntries(designatedDpnId, vmMacAddress);
+ }
+ }
+
+ public void unInstallDhcpFlowsForVms(String elanInstanceName, List<BigInteger> dpns, String vmMacAddress) {
+ for (BigInteger dpn : dpns) {
+ unInstallDhcpEntries(dpn, vmMacAddress, entityOwnershipService);
+ }
+ removeFromLocalCache(elanInstanceName, vmMacAddress);
+ }
+
+ public BigInteger readDesignatedSwitchesForExternalTunnel(IpAddress tunnelIp, String elanInstanceName) {
+ InstanceIdentifier<DesignatedSwitchForTunnel> instanceIdentifier = InstanceIdentifier.builder(DesignatedSwitchesForExternalTunnels.class).child(DesignatedSwitchForTunnel.class, new DesignatedSwitchForTunnelKey(elanInstanceName, tunnelIp)).build();
+ Optional<DesignatedSwitchForTunnel> designatedSwitchForTunnelOptional = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, instanceIdentifier);
+ if (designatedSwitchForTunnelOptional.isPresent()) {
+ return BigInteger.valueOf(designatedSwitchForTunnelOptional.get().getDpId());
+ }
+ return null;
+ }
+
+ public void writeDesignatedSwitchForExternalTunnel(BigInteger dpnId, IpAddress tunnelIp, String elanInstanceName) {
+ DesignatedSwitchForTunnelKey designatedSwitchForTunnelKey = new DesignatedSwitchForTunnelKey(elanInstanceName, tunnelIp);
+ InstanceIdentifier<DesignatedSwitchForTunnel> instanceIdentifier = InstanceIdentifier.builder(DesignatedSwitchesForExternalTunnels.class).child(DesignatedSwitchForTunnel.class, designatedSwitchForTunnelKey).build();
+ DesignatedSwitchForTunnel designatedSwitchForTunnel = new DesignatedSwitchForTunnelBuilder().setDpId(dpnId.longValue()).setElanInstanceName(elanInstanceName).setTunnelRemoteIpAddress(tunnelIp).setKey(designatedSwitchForTunnelKey).build();
+ logger.trace("Writing into CONFIG DS tunnelIp {}, elanInstanceName {}, dpnId {}", tunnelIp, elanInstanceName, dpnId);
+ MDSALDataStoreUtils.asyncUpdate(broker, LogicalDatastoreType.CONFIGURATION, instanceIdentifier, designatedSwitchForTunnel, DEFAULT_CALLBACK);
+ }
+
+ public void removeDesignatedSwitchForExternalTunnel(BigInteger dpnId, IpAddress tunnelIp, String elanInstanceName) {
+ DesignatedSwitchForTunnelKey designatedSwitchForTunnelKey = new DesignatedSwitchForTunnelKey(elanInstanceName, tunnelIp);
+ InstanceIdentifier<DesignatedSwitchForTunnel> instanceIdentifier = InstanceIdentifier.builder(DesignatedSwitchesForExternalTunnels.class).child(DesignatedSwitchForTunnel.class, designatedSwitchForTunnelKey).build();
+ logger.trace("Writing into CONFIG DS tunnelIp {}, elanInstanceName {}, dpnId {}", tunnelIp, elanInstanceName, dpnId);
+ MDSALDataStoreUtils.asyncRemove(broker, LogicalDatastoreType.CONFIGURATION, instanceIdentifier, DEFAULT_CALLBACK);
+ }
+
+ public void installDhcpDropActionOnDpn(BigInteger dpId) {
+ List<String> vmMacs = getAllVmMacs();
+ logger.trace("Installing drop actions to this new DPN {} VMs {}", dpId, vmMacs);
+ for (String vmMacAddress : vmMacs) {
+ installDhcpDropAction(dpId, vmMacAddress);
+ }
+ }
+
+ private List<String> getAllVmMacs() {
+ List<String> vmMacs = new LinkedList<String>();
+ Collection<Set<String>> listOfVmMacs = tunnelIpElanNameToVmMacCache.values();
+ for (Set<String> list : listOfVmMacs) {
+ vmMacs.addAll(list);
+ }
+ return vmMacs;
+ }
+
+ public void updateLocalCache(BigInteger designatedDpnId, IpAddress tunnelIp, String elanInstanceName) {
+ Pair<IpAddress, String> tunnelIpElanName = new ImmutablePair<IpAddress, String>(tunnelIp, elanInstanceName);
+ List<Pair<IpAddress, String>> tunnelIpElanNameList;
+ tunnelIpElanNameList = designatedDpnsToTunnelIpElanNameCache.get(designatedDpnId);
+ if (tunnelIpElanNameList == null) {
+ tunnelIpElanNameList = new LinkedList<Pair<IpAddress, String>>();
+ }
+ tunnelIpElanNameList.add(tunnelIpElanName);
+ designatedDpnsToTunnelIpElanNameCache.put(designatedDpnId, tunnelIpElanNameList);
+ }
+
+ private void updateLocalCache(IpAddress tunnelIp, String elanInstanceName, String vmMacAddress) {
+ Pair<IpAddress, String> tunnelIpElanName = new ImmutablePair<IpAddress, String>(tunnelIp, elanInstanceName);
+ Set<String> listExistingVmMacAddress;
+ listExistingVmMacAddress = tunnelIpElanNameToVmMacCache.get(tunnelIpElanName);
+ if (listExistingVmMacAddress == null) {
+ listExistingVmMacAddress = new HashSet<String>();
+ }
+ listExistingVmMacAddress.add(vmMacAddress);
+ tunnelIpElanNameToVmMacCache.put(tunnelIpElanName, listExistingVmMacAddress);
+ }
+
+ public void handleDesignatedDpnDown(BigInteger dpnId, List<BigInteger> listOfDpns) {
+ logger.trace("In handleDesignatedDpnDown dpnId {}, listOfDpns {}", dpnId, listOfDpns);
+ try {
+ List<Pair<IpAddress, String>> listOfTunnelIpElanNamePairs = designatedDpnsToTunnelIpElanNameCache.get(dpnId);
+ if (!dpnId.equals(DHCPMConstants.INVALID_DPID)) {
+ List<String> listOfVms = getAllVmMacs();
+ for (String vmMacAddress : listOfVms) {
+ unInstallDhcpEntries(dpnId, vmMacAddress);
+ }
+ }
+ if (listOfTunnelIpElanNamePairs == null || listOfTunnelIpElanNamePairs.isEmpty()) {
+ logger.trace("No tunnelIpElanName to handle for dpn {}. Returning", dpnId);
+ return;
+ }
+ for (Pair<IpAddress, String> pair : listOfTunnelIpElanNamePairs) {
+ updateCacheAndInstallNewFlows(dpnId, listOfDpns, pair);
+ }
+ } catch (Exception e) {
+ logger.error("Error in handleDesignatedDpnDown {}", e);
+ }
+ }
+
+ public void updateCacheAndInstallNewFlows(BigInteger dpnId,
+ List<BigInteger> listOfDpns, Pair<IpAddress, String> pair)
+ throws ExecutionException {
+ BigInteger newDesignatedDpn = chooseDpn(pair.getLeft(), pair.getRight(), listOfDpns);
+ if (newDesignatedDpn.equals(DHCPMConstants.INVALID_DPID)) {
+ return;
+ }
+ Set<String> listVmMacs = tunnelIpElanNameToVmMacCache.get(pair);
+ if (listVmMacs != null && !listVmMacs.isEmpty()) {
+ installDhcpFlowsForVms(pair.getLeft(), pair.getRight(), newDesignatedDpn, listVmMacs);
+ }
+ }
+
+ private void changeExistingFlowToDrop(Pair<IpAddress, String> tunnelIpElanNamePair, BigInteger dpnId) {
+ try {
+ Set<String> listVmMacAddress = tunnelIpElanNameToVmMacCache.get(tunnelIpElanNamePair);
+ if (listVmMacAddress == null || listVmMacAddress.isEmpty()) {
+ return;
+ }
+ for (String vmMacAddress : listVmMacAddress) {
+ installDhcpDropAction(dpnId, vmMacAddress);
+ }
+ } catch (Exception e) {
+ logger.error("Error in uninstallExistingFlows {}", e);
+ }
+ }
+
+ /**
+ * Choose a dpn among the list of elanDpns such that it has lowest count of being the designated dpn.
+ * @param tunnelIp
+ * @param elanInstanceName
+ * @param dpns
+ * @return
+ */
+ private BigInteger chooseDpn(IpAddress tunnelIp, String elanInstanceName,
+ List<BigInteger> dpns) {
+ BigInteger designatedDpnId = DHCPMConstants.INVALID_DPID;
+ if (dpns != null && dpns.size() != 0) {
+ List<BigInteger> candidateDpns = DhcpServiceUtils.getDpnsForElan(elanInstanceName, broker);
+ candidateDpns.retainAll(dpns);
+ logger.trace("Choosing new dpn for tunnelIp {}, elanInstanceName {}, among elanDpns {}", tunnelIp, elanInstanceName, candidateDpns);
+ boolean elanDpnAvailableFlag = true;
+ if (candidateDpns == null || candidateDpns.isEmpty()) {
+ candidateDpns = dpns;
+ elanDpnAvailableFlag = false;
+ }
+ int size = 0;
+ L2GatewayDevice device = getDeviceFromTunnelIp(elanInstanceName, tunnelIp);
+ if (device == null) {
+ logger.trace("Could not find any device for elanInstanceName {} and tunnelIp {}", elanInstanceName, tunnelIp);
+ handleUnableToDesignateDpn(tunnelIp, elanInstanceName);
+ return designatedDpnId;
+ }
+ for (BigInteger dpn : candidateDpns) {
+ String hwvtepNodeId = device.getHwvtepNodeId();
+ if (!elanDpnAvailableFlag) {
+ if (!isTunnelConfigured(dpn, hwvtepNodeId)) {
+ logger.trace("Tunnel is not configured on dpn {} to TOR {}", dpn, hwvtepNodeId);
+ continue;
+ }
+ } else if (!isTunnelUp(hwvtepNodeId, dpn)) {
+ logger.trace("Tunnel is not up between dpn {} and TOR {}", dpn, hwvtepNodeId);
+ continue;
+ }
+ List<Pair<IpAddress, String>> tunnelIpElanNameList = designatedDpnsToTunnelIpElanNameCache.get(dpn);
+ if (tunnelIpElanNameList == null) {
+ designatedDpnId = dpn;
+ break;
+ }
+ if (size == 0 || tunnelIpElanNameList.size() < size) {
+ size = tunnelIpElanNameList.size();
+ designatedDpnId = dpn;
+ }
+ }
+ writeDesignatedSwitchForExternalTunnel(designatedDpnId, tunnelIp, elanInstanceName);
+ return designatedDpnId;
+ }
+ handleUnableToDesignateDpn(tunnelIp, elanInstanceName);
+ return designatedDpnId;
+ }
+
+ private void handleUnableToDesignateDpn(IpAddress tunnelIp, String elanInstanceName) {
+ writeDesignatedSwitchForExternalTunnel(DHCPMConstants.INVALID_DPID, tunnelIp, elanInstanceName);
+ }
+
+ public void installDhcpEntries(BigInteger dpnId, String vmMacAddress) {
+ DhcpServiceUtils.setupDhcpFlowEntry(dpnId, NwConstants.DHCP_TABLE_EXTERNAL_TUNNEL, vmMacAddress, NwConstants.ADD_FLOW, mdsalUtil);
+ }
+
+ public void installDhcpEntries(final BigInteger dpnId, final String vmMacAddress, EntityOwnershipService eos) {
+ final String nodeId = DhcpServiceUtils.getNodeIdFromDpnId(dpnId);
+ ListenableFuture<Boolean> checkEntityOwnerFuture = ClusteringUtils.checkNodeEntityOwner(
+ eos, HwvtepSouthboundConstants.ELAN_ENTITY_TYPE,
+ HwvtepSouthboundConstants.ELAN_ENTITY_NAME);
+ Futures.addCallback(checkEntityOwnerFuture, new FutureCallback<Boolean>() {
+ @Override
+ public void onSuccess(Boolean isOwner) {
+ if (isOwner) {
+ installDhcpEntries(dpnId, vmMacAddress);
+ } else {
+ logger.trace("Exiting installDhcpEntries since this cluster node is not the owner for dpn {}", nodeId);
+ }
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ logger.error("Error while fetching checkNodeEntityOwner", error);
+ }
+ });
+ }
+
+ public void unInstallDhcpEntries(BigInteger dpnId, String vmMacAddress) {
+ DhcpServiceUtils.setupDhcpFlowEntry(dpnId, NwConstants.DHCP_TABLE_EXTERNAL_TUNNEL, vmMacAddress, NwConstants.DEL_FLOW, mdsalUtil);
+ }
+
+ public void unInstallDhcpEntries(final BigInteger dpnId, final String vmMacAddress, EntityOwnershipService eos) {
+ final String nodeId = DhcpServiceUtils.getNodeIdFromDpnId(dpnId);
+ ListenableFuture<Boolean> checkEntityOwnerFuture = ClusteringUtils.checkNodeEntityOwner(
+ eos, HwvtepSouthboundConstants.ELAN_ENTITY_TYPE,
+ HwvtepSouthboundConstants.ELAN_ENTITY_NAME);
+ Futures.addCallback(checkEntityOwnerFuture, new FutureCallback<Boolean>() {
+ @Override
+ public void onSuccess(Boolean isOwner) {
+ if (isOwner) {
+ unInstallDhcpEntries(dpnId, vmMacAddress);
+ } else {
+ logger.trace("Exiting unInstallDhcpEntries since this cluster node is not the owner for dpn {}", nodeId);
+ }
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ logger.error("Error while fetching checkNodeEntityOwner", error);
+ }
+ });
+ }
+
+ public void installDhcpDropAction(BigInteger dpn, String vmMacAddress) {
+ DhcpServiceUtils.setupDhcpDropAction(dpn, NwConstants.DHCP_TABLE_EXTERNAL_TUNNEL, vmMacAddress, NwConstants.ADD_FLOW, mdsalUtil);
+ }
+
+ public void installDhcpDropAction(final BigInteger dpnId, final String vmMacAddress, EntityOwnershipService eos) {
+ final String nodeId = DhcpServiceUtils.getNodeIdFromDpnId(dpnId);
+ ListenableFuture<Boolean> checkEntityOwnerFuture = ClusteringUtils.checkNodeEntityOwner(
+ eos, HwvtepSouthboundConstants.ELAN_ENTITY_TYPE,
+ HwvtepSouthboundConstants.ELAN_ENTITY_NAME);
+ Futures.addCallback(checkEntityOwnerFuture, new FutureCallback<Boolean>() {
+ @Override
+ public void onSuccess(Boolean isOwner) {
+ if (isOwner) {
+ installDhcpDropAction(dpnId, vmMacAddress);
+ } else {
+ logger.trace("Exiting installDhcpDropAction since this cluster node is not the owner for dpn {}", nodeId);
+ }
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ logger.error("Error while fetching checkNodeEntityOwner", error);
+ }
+ });
+ }
+
+ public void handleTunnelStateDown(IpAddress tunnelIp, BigInteger interfaceDpn) {
+ logger.trace("In handleTunnelStateDown tunnelIp {}, interfaceDpn {}", tunnelIp, interfaceDpn);
+ if (interfaceDpn == null) {
+ return;
+ }
+ try {
+ List<Pair<IpAddress, String>> tunnelElanPairList = designatedDpnsToTunnelIpElanNameCache.get(interfaceDpn);
+ if (tunnelElanPairList == null || tunnelElanPairList.isEmpty()) {
+ return;
+ }
+ for (Pair<IpAddress, String> tunnelElanPair : tunnelElanPairList) {
+ IpAddress tunnelIpInDpn = tunnelElanPair.getLeft();
+ if (tunnelIpInDpn.equals(tunnelIp)) {
+ List<BigInteger> dpns = DhcpServiceUtils.getListOfDpns(broker);
+ dpns.remove(interfaceDpn);
+ changeExistingFlowToDrop(tunnelElanPair, interfaceDpn);
+ updateCacheAndInstallNewFlows(interfaceDpn, dpns, tunnelElanPair);
+ }
+ }
+ } catch (Exception e) {
+ logger.error("Error in handleTunnelStateDown {}", e.getMessage());
+ logger.trace("Exception details {}", e);
+ }
+ }
+
+ private void removeFromLocalCache(String elanInstanceName, String vmMacAddress) {
+ Set<Pair<IpAddress, String>> tunnelIpElanNameKeySet = tunnelIpElanNameToVmMacCache.keySet();
+ for (Pair<IpAddress, String> pair : tunnelIpElanNameKeySet) {
+ if (pair.getRight().trim().equalsIgnoreCase(elanInstanceName.trim())) {
+ Set<String> listExistingVmMacAddress;
+ listExistingVmMacAddress = tunnelIpElanNameToVmMacCache.get(pair);
+ if (listExistingVmMacAddress == null || listExistingVmMacAddress.isEmpty()) {
+ continue;
+ }
+ listExistingVmMacAddress.remove(vmMacAddress);
+ if (listExistingVmMacAddress.size() > 0) {
+ tunnelIpElanNameToVmMacCache.put(pair, listExistingVmMacAddress);
+ return;
+ }
+ tunnelIpElanNameToVmMacCache.remove(pair);
+ }
+ }
+ }
+
+ public void removeFromLocalCache(BigInteger designatedDpnId, IpAddress tunnelIp, String elanInstanceName) {
+ Pair<IpAddress, String> tunnelIpElanName = new ImmutablePair<IpAddress, String>(tunnelIp, elanInstanceName);
+ List<Pair<IpAddress, String>> tunnelIpElanNameList;
+ tunnelIpElanNameList = designatedDpnsToTunnelIpElanNameCache.get(designatedDpnId);
+ if (tunnelIpElanNameList != null) {
+ tunnelIpElanNameList.remove(tunnelIpElanName);
+ if (tunnelIpElanNameList.size() != 0) {
+ designatedDpnsToTunnelIpElanNameCache.put(designatedDpnId, tunnelIpElanNameList);
+ } else {
+ designatedDpnsToTunnelIpElanNameCache.remove(designatedDpnId);
+ }
+ }
+ }
+
+ public void updateVniMacToPortCache(BigInteger vni, String macAddress, Port port) {
+ if (macAddress == null) {
+ return;
+ }
+ Pair<BigInteger, String> vniMacAddressPair = new ImmutablePair<BigInteger, String>(vni, macAddress.toUpperCase());
+ logger.trace("Updating vniMacAddressToPortCache with vni {} , mac {} , pair {} and port {}", vni, macAddress.toUpperCase(), vniMacAddressPair, port);
+ vniMacAddressToPortCache.put(vniMacAddressPair, port);
+ }
+
+ public void removeVniMacToPortCache(BigInteger vni, String macAddress) {
+ if (macAddress == null) {
+ return;
+ }
+ Pair<BigInteger, String> vniMacAddressPair = new ImmutablePair<BigInteger, String>(vni, macAddress.toUpperCase());
+ vniMacAddressToPortCache.remove(vniMacAddressPair);
+ }
+
+ public Port readVniMacToPortCache(BigInteger vni, String macAddress) {
+ if (macAddress == null) {
+ return null;
+ }
+ Pair<BigInteger, String> vniMacAddressPair = new ImmutablePair<BigInteger, String>(vni, macAddress.toUpperCase());
+ logger.trace("Reading vniMacAddressToPortCache with vni {} , mac {} , pair {} and port {}", vni, macAddress.toUpperCase(), vniMacAddressPair, vniMacAddressToPortCache.get(vniMacAddressPair));
+ return vniMacAddressToPortCache.get(vniMacAddressPair);
+ }
+
+ public String getExternalTunnelInterfaceName(String sourceNode, String dstNode) {
+ String tunnelInterfaceName = null;
+ Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
+ try {
+ Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> output = itmRpcService
+ .getExternalTunnelInterfaceName(new GetExternalTunnelInterfaceNameInputBuilder()
+ .setSourceNode(sourceNode).setDestinationNode(dstNode).setTunnelType(tunType).build());
+
+ RpcResult<GetExternalTunnelInterfaceNameOutput> rpcResult = output.get();
+ if (rpcResult.isSuccessful()) {
+ tunnelInterfaceName = rpcResult.getResult().getInterfaceName();
+ logger.debug("Tunnel interface name: {}", tunnelInterfaceName);
+ } else {
+ logger.warn("RPC call to ITM.GetExternalTunnelInterfaceName failed with error: {}",
+ rpcResult.getErrors());
+ }
+ } catch (NullPointerException | InterruptedException | ExecutionException e) {
+ logger.error("Failed to get external tunnel interface name for sourceNode: {} and dstNode: {}: {} ",
+ sourceNode, dstNode, e);
+ }
+ return tunnelInterfaceName;
+ }
+
+ public static Optional<Node> getNode(DataBroker dataBroker, String physicalSwitchNodeId) {
+ InstanceIdentifier<Node> psNodeId = HwvtepSouthboundUtils
+ .createInstanceIdentifier(new NodeId(physicalSwitchNodeId));
+ Optional<Node> physicalSwitchOptional = MDSALUtil.read(LogicalDatastoreType.CONFIGURATION, psNodeId, dataBroker);
+ return physicalSwitchOptional;
+ }
+
+ public RemoteMcastMacs createRemoteMcastMac(Node dstDevice, String logicalSwitchName, IpAddress internalTunnelIp) {
+ List<LocatorSet> locators = new ArrayList<>();
+ for (TerminationPoint tp : dstDevice.getTerminationPoint()) {
+ HwvtepPhysicalLocatorAugmentation aug = tp.getAugmentation(HwvtepPhysicalLocatorAugmentation.class);
+ if (internalTunnelIp.getIpv4Address().equals(aug.getDstIp().getIpv4Address())) {
+ HwvtepPhysicalLocatorRef phyLocRef = new HwvtepPhysicalLocatorRef(
+ HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(dstDevice.getNodeId(), aug));
+ locators.add(new LocatorSetBuilder().setLocatorRef(phyLocRef).build());
+ }
+ }
+ HwvtepLogicalSwitchRef lsRef = new HwvtepLogicalSwitchRef(HwvtepSouthboundUtils
+ .createLogicalSwitchesInstanceIdentifier(dstDevice.getNodeId(), new HwvtepNodeName(logicalSwitchName)));
+
+ RemoteMcastMacs remoteUcastMacs = new RemoteMcastMacsBuilder()
+ .setMacEntryKey(new MacAddress(UNKNOWN_DMAC))
+ .setLogicalSwitchRef(lsRef).setLocatorSet(locators).build();
+ return remoteUcastMacs;
+ }
+
+ private WriteTransaction putRemoteMcastMac(WriteTransaction transaction, String elanName, L2GatewayDevice device, IpAddress internalTunnelIp) {
+ Optional<Node> optionalNode = getNode(broker, device.getHwvtepNodeId());
+ Node dstNode = optionalNode.get();
+ if (dstNode == null) {
+ logger.debug("could not get device node {} ", device.getHwvtepNodeId());
+ return null;
+ }
+ RemoteMcastMacs macs = createRemoteMcastMac(dstNode, elanName, internalTunnelIp);
+ HwvtepUtils.putRemoteMcastMac(transaction, dstNode.getNodeId(), macs);
+ return transaction;
+ }
+
+ public void installRemoteMcastMac(final BigInteger designatedDpnId, final IpAddress tunnelIp, final String elanInstanceName) {
+ if (designatedDpnId.equals(DHCPMConstants.INVALID_DPID)) {
+ return;
+ }
+ ListenableFuture<Boolean> checkEntityOwnerFuture = ClusteringUtils.checkNodeEntityOwner(entityOwnershipService, HwvtepSouthboundConstants.ELAN_ENTITY_TYPE, HwvtepSouthboundConstants.ELAN_ENTITY_NAME);
+ Futures.addCallback(checkEntityOwnerFuture, new FutureCallback<Boolean>() {
+ @Override
+ public void onSuccess(Boolean isOwner) {
+ if (isOwner) {
+ logger.info("Installing remote McastMac");
+ L2GatewayDevice device = getDeviceFromTunnelIp(elanInstanceName, tunnelIp);
+ String tunnelInterfaceName = getExternalTunnelInterfaceName(String.valueOf(designatedDpnId), device.getHwvtepNodeId());
+ IpAddress internalTunnelIp = null;
+ if (tunnelInterfaceName != null) {
+ Interface tunnelInterface = DhcpServiceUtils.getInterfaceFromConfigDS(tunnelInterfaceName, broker);
+ if (tunnelInterface == null) {
+ logger.trace("Tunnel Interface is not present {}", tunnelInterfaceName);
+ return;
+ }
+ internalTunnelIp = tunnelInterface.getAugmentation(IfTunnel.class).getTunnelSource();
+ WriteTransaction transaction = broker.newWriteOnlyTransaction();
+ putRemoteMcastMac(transaction, elanInstanceName, device, internalTunnelIp);
+ if (transaction != null) {
+ transaction.submit();
+ }
+ }
+ } else {
+ logger.info("Installing remote McastMac is not executed for this node.");
+ }
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ logger.error("Failed to install remote McastMac", error);
+ }
+ });
+ }
+
+ private L2GatewayDevice getDeviceFromTunnelIp(String elanInstanceName, IpAddress tunnelIp) {
+ ConcurrentMap<String, L2GatewayDevice> devices = L2GatewayCacheUtils.getCache();
+ for (L2GatewayDevice device : devices.values()) {
+ if (device.getTunnelIp().equals(tunnelIp)) {
+ return device;
+ }
+ }
+ return null;
+ }
+
+ private boolean isTunnelUp(String nodeName, BigInteger dpn) {
+ boolean isTunnelUp = false;
+ String tunnelInterfaceName = getExternalTunnelInterfaceName(String.valueOf(dpn), nodeName);
+ if (tunnelInterfaceName == null) {
+ logger.debug("Tunnel Interface is not present {}", tunnelInterfaceName);
+ return isTunnelUp;
+ }
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface tunnelInterface = DhcpServiceUtils.getInterfaceFromOperationalDS(tunnelInterfaceName, broker);
+ if (tunnelInterface == null) {
+ logger.debug("Interface {} is not present in interface state", tunnelInterfaceName);
+ return isTunnelUp;
+ }
+ isTunnelUp = (tunnelInterface.getOperStatus() == OperStatus.Up) ? true :false;
+ return isTunnelUp;
+ }
+
+ public void handleTunnelStateUp(IpAddress tunnelIp, BigInteger interfaceDpn) {
+ logger.trace("In handleTunnelStateUp tunnelIp {}, interfaceDpn {}", tunnelIp, interfaceDpn);
+ try {
+ List<Pair<IpAddress, String>> tunnelIpElanPair = designatedDpnsToTunnelIpElanNameCache.get(DHCPMConstants.INVALID_DPID);
+ List<BigInteger> dpns = DhcpServiceUtils.getListOfDpns(broker);
+ if (tunnelIpElanPair == null || tunnelIpElanPair.isEmpty()) {
+ return;
+ }
+ for (Pair<IpAddress, String> pair : tunnelIpElanPair) {
+ if (tunnelIp.equals(pair.getLeft())) {
+ designateDpnId(tunnelIp, pair.getRight(), dpns);
+ }
+ }
+ } catch (Exception e) {
+ logger.error("Error in handleTunnelStateUp {}", e.getMessage());
+ logger.trace("Exception details {}", e);
+ }
+ }
+
+ private boolean isTunnelConfigured(BigInteger dpn, String hwVtepNodeId) {
+ String tunnelInterfaceName = getExternalTunnelInterfaceName(String.valueOf(dpn), hwVtepNodeId);
+ if (tunnelInterfaceName == null) {
+ return false;
+ }
+ Interface tunnelInterface = DhcpServiceUtils.getInterfaceFromConfigDS(tunnelInterfaceName, broker);
+ if (tunnelInterface == null) {
+ logger.debug("Tunnel Interface is not present {}", tunnelInterfaceName);
+ return false;
+ }
+ return true;
+ }
+
+ public void unInstallDhcpFlowsForVms(String elanInstanceName, IpAddress tunnelIp, List<BigInteger> dpns) {
+ Pair<IpAddress, String> tunnelIpElanNamePair = new ImmutablePair<IpAddress, String>(tunnelIp, elanInstanceName);
+ Set<String> vmMacs = tunnelIpElanNameToVmMacCache.get(tunnelIpElanNamePair);
+ logger.trace("In unInstallFlowsForVms elanInstanceName {}, tunnelIp {}, dpns {}, vmMacs {}", elanInstanceName, tunnelIp, dpns, vmMacs);
+ if (vmMacs == null) {
+ return;
+ }
+ for (String vmMacAddress : vmMacs) {
+ for (BigInteger dpn : dpns) {
+ unInstallDhcpEntries(dpn, vmMacAddress, entityOwnershipService);
+ }
+ }
+ tunnelIpElanNameToVmMacCache.remove(tunnelIpElanNamePair);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.dhcpservice;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnet.attributes.HostRoutes;
+
+public class DhcpInfo {
+ private String _clientIp;
+ private String _serverIp;
+ private String _gatewayIp;
+ private String _cidr;
+ private List<String> _dnsServers;
+ private List<HostRoutes> _hostRoutes;
+
+ public DhcpInfo() {
+ //Empty constructor
+ }
+
+ protected DhcpInfo setClientIp(String clientIp) {
+ _clientIp = clientIp;
+ return this;
+ }
+
+ protected DhcpInfo setCidr(String cidr) {
+ _cidr = cidr;
+ return this;
+ }
+
+ protected DhcpInfo setServerIp(String serverIp) {
+ _serverIp = serverIp;
+ return this;
+ }
+
+ protected DhcpInfo setGatewayIp(String gwIp) {
+ _gatewayIp = gwIp;
+ return this;
+ }
+
+ protected DhcpInfo setHostRoutes(List<HostRoutes> hostRoutes) {
+ _hostRoutes = hostRoutes;
+ return this;
+ }
+
+ protected DhcpInfo setDnsServers(List<String> dnsServers) {
+ _dnsServers = dnsServers;
+ return this;
+ }
+
+ protected DhcpInfo setDnsServersIpAddrs(List<IpAddress> dnsServers) {
+ for (IpAddress ipAddr: dnsServers) {
+ addDnsServer(ipAddr.getIpv4Address().getValue());
+ }
+ return this;
+ }
+
+ protected DhcpInfo addDnsServer(String dnsServerIp) {
+ if(_dnsServers == null) {
+ _dnsServers = new ArrayList<String>();
+ }
+ _dnsServers.add(dnsServerIp);
+ return this;
+ }
+
+
+ protected String getClientIp() {
+ return _clientIp;
+ }
+
+ protected String getCidr() {
+ return _cidr;
+ }
+
+ protected String getServerIp() {
+ return _serverIp ;
+ }
+
+ protected String getGatewayIp() {
+ return _gatewayIp ;
+ }
+
+ protected List<String> getDnsServers() {
+ return _dnsServers;
+ }
+
+ protected List<HostRoutes> getHostRoutes() {
+ return _hostRoutes;
+ }
+
+}
--- /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.dhcpservice;
+
+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.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;
+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.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DhcpInterfaceConfigListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
+
+ private static final Logger logger = LoggerFactory.getLogger(DhcpInterfaceConfigListener.class);
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private DataBroker dataBroker;
+ private DhcpExternalTunnelManager dhcpExternalTunnelManager;
+
+ public DhcpInterfaceConfigListener(DataBroker dataBroker, DhcpExternalTunnelManager dhcpExternalTunnelManager) {
+ super(Interface.class);
+ this.dataBroker = dataBroker;
+ this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
+ registerListener();
+ }
+
+ private void registerListener() {
+ try {
+ listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ getWildCardPath(), DhcpInterfaceConfigListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ logger.error("DhcpInterfaceEventListener DataChange listener registration fail!", e);
+ throw new IllegalStateException("DhcpInterfaceEventListener registration Listener failed.", e);
+ }
+ }
+
+ private InstanceIdentifier<Interface> getWildCardPath() {
+ return InstanceIdentifier.create(Interfaces.class).child(Interface.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;
+ }
+ logger.info("DhcpInterfaceConfigListener Closed");
+ }
+ @Override
+ protected void remove(InstanceIdentifier<Interface> identifier, Interface del) {
+ IfTunnel tunnelInterface = del.getAugmentation(IfTunnel.class);
+ if (tunnelInterface != null && !tunnelInterface.isInternal()) {
+ IpAddress tunnelIp = tunnelInterface.getTunnelDestination();
+ ParentRefs interfce = del.getAugmentation(ParentRefs.class);
+ if (interfce != null) {
+ dhcpExternalTunnelManager.handleTunnelStateDown(tunnelIp, interfce.getDatapathNodeIdentifier());
+ }
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Interface> identifier, Interface original, Interface update) {
+ // Handled in update () DhcpInterfaceEventListener
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Interface> identifier, Interface add) {
+ // Handled in add() DhcpInterfaceEventListener
+ }
+}
\ 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.dhcpservice;
+
+import java.math.BigInteger;
+import java.util.List;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+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.dhcpservice.api.DHCPMConstants;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.vpnservice.mdsalutil.MDSALDataStoreUtils;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+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.inet.types.rev100924.IpAddress;
+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.state.Interface;
+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.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710.InterfaceNameMacAddresses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddressKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
+
+public class DhcpInterfaceEventListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
+
+ private static final Logger logger = LoggerFactory.getLogger(DhcpInterfaceEventListener.class);
+ private DhcpManager dhcpManager;
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private DataBroker dataBroker;
+ private static final FutureCallback<Void> DEFAULT_CALLBACK = new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(Void result) {
+ logger.debug("Success in Datastore write operation");
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ logger.error("Error in Datastore write operation", error);
+ }
+ };
+ private DhcpExternalTunnelManager dhcpExternalTunnelManager;
+
+ public DhcpInterfaceEventListener(DhcpManager dhcpManager, DataBroker dataBroker, DhcpExternalTunnelManager dhcpExternalTunnelManager) {
+ super(Interface.class);
+ this.dhcpManager = dhcpManager;
+ this.dataBroker = dataBroker;
+ this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
+ registerListener();
+ }
+
+ private void registerListener() {
+ try {
+ listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), DhcpInterfaceEventListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ logger.error("DhcpInterfaceEventListener DataChange listener registration fail!", e);
+ throw new IllegalStateException("DhcpInterfaceEventListener registration Listener failed.", e);
+ }
+ }
+
+ private InstanceIdentifier<Interface> getWildCardPath() {
+ return InstanceIdentifier.create(InterfacesState.class).child(Interface.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;
+ }
+ logger.info("Interface Manager Closed");
+ }
+
+
+ @Override
+ protected void remove(InstanceIdentifier<Interface> identifier, Interface del) {
+ List<String> ofportIds = del.getLowerLayerIf();
+ if (ofportIds == null || ofportIds.isEmpty()) {
+ return;
+ }
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
+ BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
+ DhcpServiceUtils.getInterfaceFromConfigDS(del.getName(), dataBroker);
+ if (iface != null) {
+ IfTunnel tunnelInterface = iface.getAugmentation(IfTunnel.class);
+ if (tunnelInterface != null && !tunnelInterface.isInternal()) {
+ IpAddress tunnelIp = tunnelInterface.getTunnelDestination();
+ List<BigInteger> dpns = DhcpServiceUtils.getListOfDpns(dataBroker);
+ if (dpns.contains(dpId)) {
+ dhcpExternalTunnelManager.handleTunnelStateDown(tunnelIp, dpId);
+ }
+ return;
+ }
+ }
+ String interfaceName = del.getName();
+ logger.trace("Received remove DCN for interface {} dpId {}", interfaceName, dpId);
+ unInstallDhcpEntries(interfaceName, dpId);
+ dhcpManager.removeInterfaceCache(interfaceName);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Interface> identifier,
+ Interface original, Interface update) {
+ List<String> ofportIds = update.getLowerLayerIf();
+ if (ofportIds == null || ofportIds.isEmpty()) {
+ return;
+ }
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
+ BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
+ String interfaceName = update.getName();
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
+ DhcpServiceUtils.getInterfaceFromConfigDS(interfaceName, dataBroker);
+ if (iface == null) {
+ logger.trace("Interface {} is not present in the config DS", interfaceName);
+ return;
+ }
+ if (update.getType() == null) {
+ logger.trace("Interface type for interface {} is null", interfaceName);
+ return;
+ }
+ if ((original.getOperStatus().getIntValue() ^ update.getOperStatus().getIntValue()) == 0) {
+ logger.trace("Interface operstatus {} is same", update.getOperStatus());
+ return;
+ }
+ if (Tunnel.class.equals(update.getType())) {
+ IfTunnel tunnelInterface = iface.getAugmentation(IfTunnel.class);
+ if (tunnelInterface != null && !tunnelInterface.isInternal()) {
+ IpAddress tunnelIp = tunnelInterface.getTunnelDestination();
+ List<BigInteger> dpns = DhcpServiceUtils.getListOfDpns(dataBroker);
+ if (dpns.contains(dpId)) {
+ if (update.getOperStatus() == OperStatus.Down) {
+ dhcpExternalTunnelManager.handleTunnelStateDown(tunnelIp, dpId);
+ } else if (update.getOperStatus() == OperStatus.Up) {
+ dhcpExternalTunnelManager.handleTunnelStateUp(tunnelIp, dpId);
+ }
+ }
+ }
+ return;
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Interface> identifier, Interface add) {
+ String interfaceName = add.getName();
+ List<String> ofportIds = add.getLowerLayerIf();
+ if (ofportIds == null || ofportIds.isEmpty()) {
+ return;
+ }
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
+ BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
+ logger.trace("Received add DCN for interface {}, dpid {}", interfaceName, dpId);
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
+ DhcpServiceUtils.getInterfaceFromConfigDS(add.getName(), dataBroker);
+ if (iface != null) {
+ IfTunnel tunnelInterface = iface.getAugmentation(IfTunnel.class);
+ if (tunnelInterface != null && !tunnelInterface.isInternal()) {
+ IpAddress tunnelIp = tunnelInterface.getTunnelDestination();
+ List<BigInteger> dpns = DhcpServiceUtils.getListOfDpns(dataBroker);
+ if (dpns.contains(dpId)) {
+ dhcpExternalTunnelManager.handleTunnelStateUp(tunnelIp, dpId);
+ }
+ return;
+ }
+ }
+ if (!dpId.equals(DHCPMConstants.INVALID_DPID)) {
+ installDhcpEntries(interfaceName, dpId);
+ dhcpManager.updateInterfaceCache(interfaceName, new ImmutablePair<BigInteger, String>(dpId, add.getPhysAddress().getValue()));
+ }
+ }
+
+ private String getNeutronMacAddress(String interfaceName) {
+ Port port = dhcpManager.getNeutronPort(interfaceName);
+ if (port!=null) {
+ logger.trace("Port found in neutron. Interface Name {}, port {}", interfaceName, port);
+ return port.getMacAddress();
+ }
+ return null;
+ }
+
+ private void unInstallDhcpEntries(String interfaceName, BigInteger dpId) {
+ String vmMacAddress = getAndRemoveVmMacAddress(interfaceName);
+ dhcpManager.unInstallDhcpEntries(dpId, vmMacAddress);
+ }
+
+ private void installDhcpEntries(String interfaceName, BigInteger dpId) {
+ String vmMacAddress = getAndUpdateVmMacAddress(interfaceName);
+ dhcpManager.installDhcpEntries(dpId, vmMacAddress);
+ }
+
+ private String getAndUpdateVmMacAddress(String interfaceName) {
+ InstanceIdentifier<InterfaceNameMacAddress> instanceIdentifier = InstanceIdentifier.builder(InterfaceNameMacAddresses.class).child(InterfaceNameMacAddress.class, new InterfaceNameMacAddressKey(interfaceName)).build();
+ Optional<InterfaceNameMacAddress> existingEntry = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier);
+ if (!existingEntry.isPresent()) {
+ logger.trace("Entry for interface {} missing in InterfaceNameVmMacAddress map", interfaceName);
+ String vmMacAddress = getNeutronMacAddress(interfaceName);
+ if (vmMacAddress==null || vmMacAddress.isEmpty()) {
+ return null;
+ }
+ logger.trace("Updating InterfaceNameVmMacAddress map with {}, {}", interfaceName,vmMacAddress);
+ InterfaceNameMacAddress interfaceNameMacAddress = new InterfaceNameMacAddressBuilder().setKey(new InterfaceNameMacAddressKey(interfaceName)).setInterfaceName(interfaceName).setMacAddress(vmMacAddress).build();
+ MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier, interfaceNameMacAddress);
+ return vmMacAddress;
+ }
+ return existingEntry.get().getMacAddress();
+ }
+
+ private String getAndRemoveVmMacAddress(String interfaceName) {
+ InstanceIdentifier<InterfaceNameMacAddress> instanceIdentifier = InstanceIdentifier.builder(InterfaceNameMacAddresses.class).child(InterfaceNameMacAddress.class, new InterfaceNameMacAddressKey(interfaceName)).build();
+ Optional<InterfaceNameMacAddress> existingEntry = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier);
+ if (existingEntry.isPresent()) {
+ String vmMacAddress = existingEntry.get().getMacAddress();
+ logger.trace("Entry for interface found in InterfaceNameVmMacAddress map {}, {}", interfaceName, vmMacAddress);
+ MDSALDataStoreUtils.asyncRemove(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier, DEFAULT_CALLBACK);
+ return vmMacAddress;
+ }
+ logger.trace("Entry for interface {} missing in InterfaceNameVmMacAddress map", interfaceName);
+ 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.dhcpservice;
+
+import java.math.BigInteger;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
+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.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.datastoreutils.AsyncClusteredDataChangeListenerBase;
+import org.opendaylight.vpnservice.dhcpservice.api.DHCPMConstants;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.utils.L2GatewayCacheUtils;
+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.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.Devices;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.connections.attributes.L2gatewayConnections;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.connections.attributes.l2gatewayconnections.L2gatewayConnection;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateways.attributes.L2gateways;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateways.attributes.l2gateways.L2gateway;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateways.attributes.l2gateways.L2gatewayKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class DhcpL2GatewayConnectionListener extends AsyncClusteredDataChangeListenerBase<L2gatewayConnection,DhcpL2GatewayConnectionListener> implements AutoCloseable {
+
+ private static final Logger logger = LoggerFactory.getLogger(DhcpInterfaceEventListener.class);
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
+ private final DataBroker dataBroker;
+
+ public DhcpL2GatewayConnectionListener(DataBroker dataBroker, DhcpExternalTunnelManager dhcpExternalTunnelManager) {
+ super(L2gatewayConnection.class, DhcpL2GatewayConnectionListener.class);
+ this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
+ this.dataBroker = dataBroker;
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<L2gatewayConnection> identifier,
+ L2gatewayConnection del) {
+ Uuid gatewayId = del.getL2gatewayId();
+ InstanceIdentifier<L2gateway> inst = InstanceIdentifier.create(Neutron.class).child(L2gateways.class)
+ .child(L2gateway.class, new L2gatewayKey(gatewayId));
+ Optional<L2gateway> l2Gateway = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, inst);
+ if (!l2Gateway.isPresent()) {
+ logger.trace("L2Gw not present id {}", gatewayId);
+ return;
+ }
+ Uuid networkUuid = del.getNetworkId();
+ boolean isLastConnection = isLastGatewayConnection(networkUuid);
+ if (!isLastConnection) {
+ logger.trace("Not the last L2GatewayConnection. Not removing flows.");
+ return;
+ }
+ List<Devices> l2Devices = l2Gateway.get().getDevices();
+ for (Devices l2Device : l2Devices) {
+ String l2DeviceName = l2Device.getDeviceName();
+ L2GatewayDevice l2GatewayDevice = L2GatewayCacheUtils.getL2DeviceFromCache(l2DeviceName);
+ IpAddress tunnelIp = l2GatewayDevice.getTunnelIp();
+ BigInteger designatedDpnId = dhcpExternalTunnelManager.readDesignatedSwitchesForExternalTunnel(tunnelIp, del.getNetworkId().getValue());
+ if (designatedDpnId == null || designatedDpnId.equals(DHCPMConstants.INVALID_DPID)) {
+ logger.error("Could not find desiganted DPN ID");
+ return;
+ }
+ dhcpExternalTunnelManager.removeDesignatedSwitchForExternalTunnel(designatedDpnId, tunnelIp, del.getNetworkId().getValue());
+ }
+ }
+
+ private boolean isLastGatewayConnection(Uuid networkUuid) {
+ boolean isLastConnection = true;
+ InstanceIdentifier<L2gatewayConnections> l2gatewayConnectionIdentifier = InstanceIdentifier.create(Neutron.class).child(L2gatewayConnections.class);
+ Optional<L2gatewayConnections> l2GwConnection = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, l2gatewayConnectionIdentifier);
+ List<L2gatewayConnection> l2GatewayConnectionList = l2GwConnection.get().getL2gatewayConnection();
+ for (L2gatewayConnection l2gatewayConnection : l2GatewayConnectionList) {
+ if (networkUuid.equals(l2gatewayConnection.getNetworkId())) {
+ isLastConnection = false;
+ break;
+ }
+ }
+ return isLastConnection;
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<L2gatewayConnection> identifier,
+ L2gatewayConnection original, L2gatewayConnection update) {
+
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<L2gatewayConnection> identifier,
+ L2gatewayConnection add) {
+
+ }
+
+ @Override
+ protected InstanceIdentifier<L2gatewayConnection> getWildCardPath() {
+ return InstanceIdentifier.create(Neutron.class).child(L2gatewayConnections.class)
+ .child(L2gatewayConnection.class);
+ }
+
+ @Override
+ protected ClusteredDataChangeListener getDataChangeListener() {
+ return DhcpL2GatewayConnectionListener.this;
+ }
+
+ @Override
+ protected DataChangeScope getDataChangeScope() {
+ return AsyncDataBroker.DataChangeScope.SUBTREE;
+ }
+
+ @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;
+ }
+ logger.info("DhcpL2GatewayConnection listener Closed");
+ }
+}
--- /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.dhcpservice;
+
+import java.math.BigInteger;
+import java.util.List;
+import java.util.concurrent.ConcurrentMap;
+
+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.dhcpservice.api.DHCPMConstants;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.utils.L2GatewayCacheUtils;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepSouthboundConstants;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DhcpLogicalSwitchListener extends AbstractDataChangeListener<LogicalSwitches> implements AutoCloseable {
+
+ private static final Logger logger = LoggerFactory.getLogger(DhcpLogicalSwitchListener.class);
+ private DhcpExternalTunnelManager dhcpExternalTunnelManager;
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private DataBroker dataBroker;
+
+ public DhcpLogicalSwitchListener(DhcpExternalTunnelManager dhcpManager, DataBroker dataBroker) {
+ super(LogicalSwitches.class);
+ this.dhcpExternalTunnelManager = dhcpManager;
+ this.dataBroker = dataBroker;
+ registerListener();
+ }
+
+ private void registerListener() {
+ try {
+ listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), DhcpLogicalSwitchListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ logger.error("DhcpLogicalSwitchListener DataChange listener registration fail!", e);
+ throw new IllegalStateException("DhcpLogicalSwitchListener registration Listener failed.", e);
+ }
+ }
+
+ private InstanceIdentifier<LogicalSwitches> getWildCardPath() {
+ return InstanceIdentifier.create(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID))
+ .child(Node.class).augmentation(HwvtepGlobalAugmentation.class)
+ .child(LogicalSwitches.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;
+ }
+ logger.info("DhcpLogicalSwitchListener Closed");
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<LogicalSwitches> identifier,
+ LogicalSwitches del) {
+ logger.trace("Received LogicalSwitch remove DCN");
+ String elanInstanceName = del.getLogicalSwitchUuid().toString();
+ ConcurrentMap<String, L2GatewayDevice> devices = L2GatewayCacheUtils.getCache();
+ String nodeId = identifier.firstKeyOf(Node.class).getNodeId().getValue();
+ L2GatewayDevice targetDevice = null;
+ for (L2GatewayDevice device : devices.values()) {
+ if (nodeId.equals(device.getHwvtepNodeId())) {
+ targetDevice = device;
+ break;
+ }
+ }
+ if (targetDevice == null) {
+ logger.error("Logical Switch Device with name {} is not present in L2GW cache", elanInstanceName);
+ return;
+ }
+ IpAddress tunnelIp = targetDevice.getTunnelIp();
+ handleLogicalSwitchRemove(elanInstanceName, tunnelIp);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<LogicalSwitches> identifier,
+ LogicalSwitches original, LogicalSwitches update) {
+ logger.trace("Received LogicalSwitch update DCN");
+
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<LogicalSwitches> identifier,
+ LogicalSwitches add) {
+ logger.trace("Received LogicalSwitch add DCN");
+ String elanInstanceName = add.getHwvtepNodeName().getValue();
+ ConcurrentMap<String, L2GatewayDevice> devices = L2GatewayCacheUtils.getCache();
+ String nodeId = identifier.firstKeyOf(Node.class).getNodeId().getValue();
+ L2GatewayDevice targetDevice = null;
+ for (L2GatewayDevice device : devices.values()) {
+ if (nodeId.equals(device.getHwvtepNodeId())) {
+ targetDevice = device;
+ break;
+ }
+ }
+ if (targetDevice == null) {
+ logger.error("Logical Switch Device with name {} is not present in L2GW cache", elanInstanceName);
+ return;
+ }
+ IpAddress tunnelIp = targetDevice.getTunnelIp();
+ handleLogicalSwitchAdd(elanInstanceName, tunnelIp);
+
+ }
+
+ private void handleLogicalSwitchRemove(String elanInstanceName, IpAddress tunnelIp) {
+ BigInteger designatedDpnId;
+ designatedDpnId = dhcpExternalTunnelManager.readDesignatedSwitchesForExternalTunnel(tunnelIp, elanInstanceName);
+ if (designatedDpnId == null || designatedDpnId.equals(DHCPMConstants.INVALID_DPID)) {
+ logger.info("Could not find designated DPN ID");
+ return;
+ }
+ dhcpExternalTunnelManager.removeDesignatedSwitchForExternalTunnel(designatedDpnId, tunnelIp, elanInstanceName);
+ }
+
+ private void handleLogicalSwitchAdd(String elanInstanceName, IpAddress tunnelIp) {
+ List<BigInteger> dpns = DhcpServiceUtils.getListOfDpns(dataBroker);
+ BigInteger designatedDpnId;
+ designatedDpnId = dhcpExternalTunnelManager.designateDpnId(tunnelIp, elanInstanceName, dpns);
+ if (designatedDpnId == null || designatedDpnId.equals(DHCPMConstants.INVALID_DPID)) {
+ logger.info("Unable to designate a DPN");
+ return;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.dhcpservice;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.vpnservice.dhcpservice.api.DHCPMConstants;
+import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
+import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
+import org.opendaylight.vpnservice.mdsalutil.InstructionType;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.vpnservice.neutronvpn.interfaces.INeutronVpnManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DhcpManager implements AutoCloseable {
+
+ private static final Logger logger = LoggerFactory.getLogger(DhcpManager.class);
+ private final DataBroker broker;
+ IMdsalApiManager mdsalUtil;
+
+ private int dhcpOptLeaseTime = 0;
+ private int dhcpOptRenewalTime = 0;
+ private int dhcpOptRebindingTime = 0;
+ private String dhcpOptDefDomainName;
+ private INeutronVpnManager neutronVpnService;
+ // cache used to maintain DpnId and physical address for each interface.
+ private static HashMap<String, ImmutablePair<BigInteger, String>> interfaceToDpnIdMacAddress = new HashMap<String, ImmutablePair<BigInteger, String>>();
+
+ /**
+ * @param db - dataBroker reference
+ */
+ public DhcpManager(final DataBroker db) {
+ broker = db;
+ configureLeaseDuration(DHCPMConstants.DEFAULT_LEASE_TIME);
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalUtil = mdsalManager;
+ }
+
+ public void setNeutronVpnService(INeutronVpnManager neutronVpnService) {
+ logger.debug("Setting NeutronVpn dependency");
+ this.neutronVpnService = neutronVpnService;
+ }
+
+ @Override
+ public void close() throws Exception {
+ logger.info("DHCP Manager Closed");
+ }
+
+ public int setLeaseDuration(int leaseDuration) {
+ configureLeaseDuration(leaseDuration);
+ return getDhcpLeaseTime();
+ }
+
+ public String setDefaultDomain(String defaultDomain) {
+ this.dhcpOptDefDomainName = defaultDomain;
+ return getDhcpDefDomain();
+ }
+
+ protected int getDhcpLeaseTime() {
+ return this.dhcpOptLeaseTime;
+ }
+
+ protected int getDhcpRenewalTime() {
+ return this.dhcpOptLeaseTime;
+ }
+
+ protected int getDhcpRebindingTime() {
+ return this.dhcpOptLeaseTime;
+ }
+
+ protected String getDhcpDefDomain() {
+ return this.dhcpOptDefDomainName;
+ }
+
+ private void configureLeaseDuration(int leaseTime) {
+ this.dhcpOptLeaseTime = leaseTime;
+ if(leaseTime > 0) {
+ this.dhcpOptRenewalTime = this.dhcpOptLeaseTime/2;
+ this.dhcpOptRebindingTime = (this.dhcpOptLeaseTime*7)/8;
+ } else {
+ this.dhcpOptRenewalTime = -1;
+ this.dhcpOptRebindingTime = -1;
+ }
+ }
+
+ public Subnet getNeutronSubnet(Port nPort) {
+ if (nPort != null) {
+ try {
+ return neutronVpnService.getNeutronSubnet(nPort.getFixedIps().get(0).getSubnetId());
+ } catch (Exception e) {
+ logger.warn("Failed to get Neutron Subnet from Port: {}", e);
+ }
+ }
+ return null;
+ }
+
+ public Port getNeutronPort(String name) {
+ try {
+ return neutronVpnService.getNeutronPort(name);
+ } catch (IllegalArgumentException e) {
+ return null;
+ } catch (Exception ex) {
+ logger.trace("In getNeutronPort interface name passed {} exception message {}.", name, ex.getMessage());
+ return null;
+ }
+ }
+
+ public void installDhcpEntries(BigInteger dpnId, String vmMacAddress) {
+ DhcpServiceUtils.setupDhcpFlowEntry(dpnId, NwConstants.DHCP_TABLE, vmMacAddress, NwConstants.ADD_FLOW, mdsalUtil);
+ }
+
+ public void unInstallDhcpEntries(BigInteger dpId, String vmMacAddress) {
+ DhcpServiceUtils.setupDhcpFlowEntry(dpId, NwConstants.DHCP_TABLE, vmMacAddress, NwConstants.DEL_FLOW, mdsalUtil);
+ }
+
+ public void setupTableMissForDhcpTable(BigInteger dpId) {
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.LPORT_DISPATCHER_TABLE }));
+
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.DHCP_TABLE, "DHCPTableMissFlow",
+ 0, "DHCP Table Miss Flow", 0, 0,
+ DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions);
+ mdsalUtil.installFlow(flowEntity);
+ setupTableMissForHandlingExternalTunnel(dpId);
+ }
+
+ private void setupTableMissForHandlingExternalTunnel(BigInteger dpId) {
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.EXTERNAL_TUNNEL_TABLE }));
+
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.DHCP_TABLE_EXTERNAL_TUNNEL, "DHCPTableMissFlowForExternalTunnel",
+ 0, "DHCP Table Miss Flow For External Tunnel", 0, 0,
+ DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions);
+ mdsalUtil.installFlow(flowEntity);
+ }
+
+ public void updateInterfaceCache(String interfaceName, ImmutablePair<BigInteger, String> pair) {
+ interfaceToDpnIdMacAddress.put(interfaceName, pair);
+ }
+
+ public ImmutablePair<BigInteger, String> getInterfaceCache(String interfaceName) {
+ return interfaceToDpnIdMacAddress.get(interfaceName);
+ }
+
+ public void removeInterfaceCache(String interfaceName) {
+ interfaceToDpnIdMacAddress.remove(interfaceName);
+ }
+}
--- /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.dhcpservice;
+
+import java.math.BigInteger;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
+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.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.vpnservice.datastoreutils.AsyncClusteredDataChangeListenerBase;
+import org.opendaylight.vpnservice.neutronvpn.api.utils.NeutronUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DhcpNeutronPortListener extends AsyncClusteredDataChangeListenerBase<Port, DhcpNeutronPortListener> implements AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DhcpNeutronPortListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private DhcpExternalTunnelManager dhcpExternalTunnelManager;
+ private DataBroker broker;
+
+ public DhcpNeutronPortListener(final DataBroker db, final DhcpExternalTunnelManager dhcpExternalTunnelManager) {
+ super(Port.class, DhcpNeutronPortListener.class);
+ this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
+ this.broker = db;
+ }
+
+ @Override
+ protected InstanceIdentifier<Port> getWildCardPath() {
+ return InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DhcpNeutronPortListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.debug("DhcpNeutronPortListener Listener Closed");
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Port> identifier, Port del) {
+ LOG.trace("Port removed: {}", del);
+ if(NeutronUtils.isPortVnicTypeNormal(del)) {
+ return;
+ }
+ String macAddress = del.getMacAddress();
+ Uuid networkId = del.getNetworkId();
+ String segmentationId = DhcpServiceUtils.getSegmentationId(networkId, broker);
+ if (segmentationId == null) {
+ return;
+ }
+ List<BigInteger> listOfDpns = DhcpServiceUtils.getListOfDpns(broker);
+ dhcpExternalTunnelManager.unInstallDhcpFlowsForVms(networkId.getValue(), listOfDpns, macAddress);
+ dhcpExternalTunnelManager.removeVniMacToPortCache(new BigInteger(segmentationId), macAddress);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Port> identifier, Port original, Port update) {
+ LOG.trace("Port changed to {}", update);
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Port> identifier, Port add) {
+ LOG.trace("Port added {}", add);
+ if(NeutronUtils.isPortVnicTypeNormal(add)) {
+ LOG.trace("Port is normal {}", add);
+ return;
+ }
+ String macAddress = add.getMacAddress();
+ Uuid networkId = add.getNetworkId();
+ String segmentationId = DhcpServiceUtils.getSegmentationId(networkId, broker);
+ if (segmentationId == null) {
+ LOG.trace("segmentation id is null");
+ return;
+ }
+ dhcpExternalTunnelManager.updateVniMacToPortCache(new BigInteger(segmentationId), macAddress, add);
+ }
+
+ @Override
+ protected ClusteredDataChangeListener getDataChangeListener() {
+ return DhcpNeutronPortListener.this;
+ }
+
+ @Override
+ protected DataChangeScope getDataChangeScope() {
+ return AsyncDataBroker.DataChangeScope.SUBTREE;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.dhcpservice;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.net.util.SubnetUtils;
+import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
+import org.opendaylight.controller.liblldp.EtherTypes;
+import org.opendaylight.controller.liblldp.NetUtils;
+import org.opendaylight.controller.liblldp.PacketException;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.dhcpservice.api.DHCP;
+import org.opendaylight.vpnservice.dhcpservice.api.DHCPConstants;
+import org.opendaylight.vpnservice.dhcpservice.api.DHCPMConstants;
+import org.opendaylight.vpnservice.dhcpservice.api.DHCPUtils;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.packet.Ethernet;
+import org.opendaylight.vpnservice.mdsalutil.packet.IEEE8021Q;
+import org.opendaylight.vpnservice.mdsalutil.packet.IPProtocols;
+import org.opendaylight.vpnservice.mdsalutil.packet.IPv4;
+import org.opendaylight.vpnservice.mdsalutil.packet.UDP;
+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.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnet.attributes.HostRoutes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+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.PacketProcessingService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.SendToController;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
+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.GetInterfaceFromIfIndexInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexOutput;
+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.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class DhcpPktHandler implements AutoCloseable, PacketProcessingListener {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DhcpPktHandler.class);
+ private final DataBroker dataBroker;
+ private final DhcpManager dhcpMgr;
+ private OdlInterfaceRpcService interfaceManagerRpc;
+ private boolean computeUdpChecksum = true;
+ private PacketProcessingService pktService;
+ private DhcpExternalTunnelManager dhcpExternalTunnelManager;
+
+ public DhcpPktHandler(final DataBroker broker, final DhcpManager dhcpManager, final DhcpExternalTunnelManager dhcpExternalTunnelManager) {
+ this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
+ this.dataBroker = broker;
+ dhcpMgr = dhcpManager;
+ }
+
+ //TODO: Handle this in a separate thread
+ @Override
+ public void onPacketReceived(PacketReceived packet) {
+ Class<? extends PacketInReason> pktInReason = packet.getPacketInReason();
+ if (isPktInReasonSendtoCtrl(pktInReason)) {
+ byte[] inPayload = packet.getPayload();
+ Ethernet ethPkt = new Ethernet();
+ try {
+ ethPkt.deserialize(inPayload, 0, inPayload.length * NetUtils.NumBitsInAByte);
+ } catch (Exception e) {
+ LOG.warn("Failed to decode DHCP Packet {}", e);
+ LOG.trace("Received packet {}", packet);
+ return;
+ }
+ try {
+ DHCP pktIn;
+ pktIn = getDhcpPktIn(ethPkt);
+ if (pktIn != null) {
+ LOG.trace("DHCPPkt received: {}", pktIn);
+ LOG.trace("Received Packet: {}", packet);
+ BigInteger metadata = packet.getMatch().getMetadata().getMetadata();
+ long portTag = MetaDataUtil.getLportFromMetadata(metadata).intValue();
+ String macAddress = DHCPUtils.byteArrayToString(ethPkt.getSourceMACAddress());
+ BigInteger tunnelId = packet.getMatch().getTunnel() == null ? null : packet.getMatch().getTunnel().getTunnelId();
+ String interfaceName = getInterfaceNameFromTag(portTag);
+ ImmutablePair<BigInteger, String> pair = getDpnIdPhysicalAddressFromInterfaceName(interfaceName);
+ DHCP replyPkt = handleDhcpPacket(pktIn, interfaceName, macAddress, tunnelId);
+ byte[] pktOut = getDhcpPacketOut(replyPkt, ethPkt, pair.getRight());
+ sendPacketOut(pktOut, pair.getLeft(), interfaceName, tunnelId);
+ }
+ } catch (Exception e) {
+ LOG.warn("Failed to get DHCP Reply");
+ LOG.trace("Reason for failure {}", e);
+ }
+ }
+ }
+
+ private void sendPacketOut(byte[] pktOut, BigInteger dpnId, String interfaceName, BigInteger tunnelId) {
+ LOG.trace("Sending packet out DpId {}, portId {}, vlanId {}, interfaceName {}", dpnId, interfaceName);
+ List<Action> action = getEgressAction(interfaceName, tunnelId);
+ TransmitPacketInput output = MDSALUtil.getPacketOut(action, pktOut, dpnId);
+ LOG.trace("Transmitting packet: {}",output);
+ this.pktService.transmitPacket(output);
+ }
+
+ private DHCP handleDhcpPacket(DHCP dhcpPkt, String interfaceName, String macAddress, BigInteger tunnelId) {
+ LOG.debug("DHCP pkt rcvd {}", dhcpPkt);
+ byte msgType = dhcpPkt.getMsgType();
+ if (msgType == DHCPConstants.MSG_DECLINE) {
+ LOG.debug("DHCPDECLINE received");
+ return null;
+ } else if (msgType == DHCPConstants.MSG_RELEASE) {
+ LOG.debug("DHCPRELEASE received");
+ return null;
+ }
+ Port nPort;
+ if (tunnelId != null) {
+ nPort = dhcpExternalTunnelManager.readVniMacToPortCache(tunnelId, macAddress);
+ } else {
+ nPort = getNeutronPort(interfaceName);
+ }
+ Subnet nSubnet = getNeutronSubnet(nPort);
+ DhcpInfo dhcpInfo = getDhcpInfo(nPort, nSubnet);
+ LOG.trace("NeutronPort: {} \n NeutronSubnet: {}, dhcpInfo{}",nPort, nSubnet, dhcpInfo);
+ DHCP reply = null;
+ if (dhcpInfo != null) {
+ if (msgType == DHCPConstants.MSG_DISCOVER) {
+ reply = getReplyToDiscover(dhcpPkt, dhcpInfo);
+ } else if (msgType == DHCPConstants.MSG_REQUEST) {
+ reply = getReplyToRequest(dhcpPkt, dhcpInfo);
+ }
+ }
+
+ return reply;
+ }
+
+ private DhcpInfo getDhcpInfo(Port nPort, Subnet nSubnet) {
+ DhcpInfo dhcpInfo = null;
+ if( (nPort != null) && (nSubnet != null) ) {
+ String clientIp = nPort.getFixedIps().get(0).getIpAddress().getIpv4Address().getValue();
+ String serverIp = nSubnet.getGatewayIp().getIpv4Address().getValue();
+ List<IpAddress> dnsServers = nSubnet.getDnsNameservers();
+ dhcpInfo = new DhcpInfo();
+ dhcpInfo.setClientIp(clientIp).setServerIp(serverIp)
+ .setCidr(nSubnet.getCidr()).setHostRoutes(nSubnet.getHostRoutes())
+ .setDnsServersIpAddrs(dnsServers).setGatewayIp(serverIp);
+ }
+ return dhcpInfo;
+ }
+
+ private Subnet getNeutronSubnet(Port nPort) {
+ return dhcpMgr.getNeutronSubnet(nPort);
+ }
+
+ private Port getNeutronPort(String interfaceName) {
+ return dhcpMgr.getNeutronPort(interfaceName);
+ }
+
+ private DHCP getDhcpPktIn(Ethernet actualEthernetPacket) {
+ Ethernet ethPkt = actualEthernetPacket;
+ if (ethPkt.getEtherType() == (short)NwConstants.ETHTYPE_802_1Q) {
+ ethPkt = (Ethernet)ethPkt.getPayload();
+ }
+ if (ethPkt.getPayload() instanceof IPv4) {
+ IPv4 ipPkt = (IPv4) ethPkt.getPayload();
+ if (ipPkt.getPayload() instanceof UDP) {
+ UDP udpPkt = (UDP) ipPkt.getPayload();
+ if ((udpPkt.getSourcePort() == DHCPMConstants.dhcpClientPort)
+ && (udpPkt.getDestinationPort() == DHCPMConstants.dhcpServerPort)) {
+ LOG.trace("Matched dhcpClientPort and dhcpServerPort");
+ byte[] rawDhcpPayload = udpPkt.getRawPayload();
+ DHCP reply = new DHCP();
+ try {
+ reply.deserialize(rawDhcpPayload, 0, rawDhcpPayload.length);
+ } catch (PacketException e) {
+ LOG.warn("Failed to deserialize DHCP pkt");
+ LOG.trace("Reason for failure {}", e);
+ return null;
+ }
+ return reply;
+ }
+ }
+ }
+ return null;
+ }
+
+ DHCP getReplyToDiscover(DHCP dhcpPkt, DhcpInfo dhcpInfo) {
+ DHCP reply = new DHCP();
+ reply.setOp(DHCPConstants.BOOTREPLY);
+ reply.setHtype(dhcpPkt.getHtype());
+ reply.setHlen(dhcpPkt.getHlen());
+ reply.setHops((byte) 0);
+ reply.setXid(dhcpPkt.getXid());
+ reply.setSecs((short) 0);
+
+ reply.setYiaddr(dhcpInfo.getClientIp());
+ reply.setSiaddr(dhcpInfo.getServerIp());
+
+ reply.setFlags(dhcpPkt.getFlags());
+ reply.setGiaddr(dhcpPkt.getGiaddr());
+ reply.setChaddr(dhcpPkt.getChaddr());
+
+ reply.setMsgType(DHCPConstants.MSG_OFFER);
+ if(dhcpPkt.containsOption(DHCPConstants.OPT_PARAMETER_REQUEST_LIST)) {
+ setParameterListOptions(dhcpPkt, reply, dhcpInfo);
+ }
+ setCommonOptions(reply, dhcpInfo);
+ return reply;
+ }
+
+ DHCP getReplyToRequest(DHCP dhcpPkt, DhcpInfo dhcpInfo) {
+ boolean sendAck = false;
+ byte[] requestedIp = null;
+ DHCP reply = new DHCP();
+ reply.setOp(DHCPConstants.BOOTREPLY);
+ reply.setHtype(dhcpPkt.getHtype());
+ reply.setHlen(dhcpPkt.getHlen());
+ reply.setHops((byte) 0);
+ reply.setXid(dhcpPkt.getXid());
+ reply.setSecs((short) 0);
+
+ reply.setFlags(dhcpPkt.getFlags());
+ reply.setGiaddr(dhcpPkt.getGiaddr());
+ reply.setChaddr(dhcpPkt.getChaddr());
+ byte[] allocatedIp = DHCPUtils.strAddrToByteArray(dhcpInfo.getClientIp());
+ if(Arrays.equals(allocatedIp, dhcpPkt.getCiaddr())) {
+ //This means a renew request
+ sendAck = true;
+ } else {
+ requestedIp = dhcpPkt.getOptionBytes(DHCPConstants.OPT_REQUESTED_ADDRESS);
+ sendAck = Arrays.equals(allocatedIp, requestedIp);
+ }
+
+ if (sendAck) {
+ reply.setCiaddr(dhcpPkt.getCiaddr());
+ reply.setYiaddr(dhcpInfo.getClientIp());
+ reply.setSiaddr(dhcpInfo.getServerIp());
+ reply.setMsgType(DHCPConstants.MSG_ACK);
+ if(dhcpPkt.containsOption(DHCPConstants.OPT_PARAMETER_REQUEST_LIST)) {
+ setParameterListOptions(dhcpPkt, reply, dhcpInfo);
+ }
+ setCommonOptions(reply, dhcpInfo);
+ }
+ else {
+ reply.setMsgType(DHCPConstants.MSG_NAK);
+ }
+ return reply;
+ }
+
+ protected byte[] getDhcpPacketOut(DHCP reply, Ethernet etherPkt, String phyAddrees) {
+ if (reply == null) {
+ /*
+ * DECLINE or RELEASE don't result in reply packet
+ */
+ return null;
+ }
+ LOG.debug("Sending DHCP Pkt {}", reply);
+ // create UDP pkt
+ UDP udpPkt = new UDP();
+ byte[] rawPkt;
+ try {
+ rawPkt = reply.serialize();
+ } catch (PacketException e2) {
+ // TODO Auto-generated catch block
+ e2.printStackTrace();
+ return null;
+ }
+ udpPkt.setRawPayload(rawPkt);
+ udpPkt.setDestinationPort(DHCPMConstants.dhcpClientPort);
+ udpPkt.setSourcePort(DHCPMConstants.dhcpServerPort);
+ udpPkt.setLength((short) (rawPkt.length + 8));
+ //Create IP Pkt
+ IPv4 ip4Reply = new IPv4();
+ try {
+ rawPkt = udpPkt.serialize();
+ } catch (PacketException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return null;
+ }
+ short checkSum = 0;
+ if(this.computeUdpChecksum) {
+ checkSum = computeChecksum(rawPkt, reply.getSiaddr(),
+ NetUtils.intToByteArray4(DHCPMConstants.BCAST_IP));
+ }
+ udpPkt.setChecksum(checkSum);
+ ip4Reply.setPayload(udpPkt);
+ ip4Reply.setProtocol(IPProtocols.UDP.byteValue());
+ ip4Reply.setSourceAddress(reply.getSiaddrAsInetAddr());
+ ip4Reply.setDestinationAddress(DHCPMConstants.BCAST_IP);
+ ip4Reply.setTotalLength((short) (rawPkt.length+20));
+ ip4Reply.setTtl((byte) 32);
+ // create Ethernet Frame
+ Ethernet ether = new Ethernet();
+ if (etherPkt.getEtherType() == (short)NwConstants.ETHTYPE_802_1Q) {
+ IEEE8021Q vlanPacket = (IEEE8021Q) etherPkt.getPayload();
+ IEEE8021Q vlanTagged = new IEEE8021Q();
+ vlanTagged.setCFI(vlanPacket.getCfi());
+ vlanTagged.setPriority(vlanPacket.getPriority());
+ vlanTagged.setVlanId(vlanPacket.getVlanId());
+ vlanTagged.setPayload(ip4Reply);
+ vlanTagged.setEtherType(EtherTypes.IPv4.shortValue());
+ ether.setPayload(vlanTagged);
+ ether.setEtherType((short) NwConstants.ETHTYPE_802_1Q);
+ } else {
+ ether.setEtherType(EtherTypes.IPv4.shortValue());
+ ether.setPayload(ip4Reply);
+ }
+ ether.setSourceMACAddress(getServerMacAddress(phyAddrees));
+ ether.setDestinationMACAddress(etherPkt.getSourceMACAddress());
+
+ try {
+ rawPkt = ether.serialize();
+ } catch (PacketException e) {
+ LOG.warn("Failed to serialize ethernet reply",e);
+ return null;
+ }
+ return rawPkt;
+ }
+
+ private byte[] getServerMacAddress(String phyAddress) {
+ // Should we return ControllerMac instead?
+ return DHCPUtils.strMacAddrtoByteArray(phyAddress);
+ }
+
+ public short computeChecksum(byte[] inData, byte[] srcAddr, byte[] destAddr) {
+ short checkSum = (short) 0;
+ int sum = 0, carry = 0;
+ int wordData, i;
+
+ for (i = 0; i < inData.length - 1; i = i + 2) {
+ // Skip, if the current bytes are checkSum bytes
+ wordData = ((inData[i] << 8) & 0xFF00) + (inData[i + 1] & 0xFF);
+ sum = sum + wordData;
+ }
+
+ if (i < inData.length) {
+ wordData = ((inData[i] << 8) & 0xFF00) + (0 & 0xFF);
+ sum = sum + wordData;
+ }
+
+ for (i = 0; i < 4; i = i + 2) {
+ wordData = ((srcAddr[i] << 8) & 0xFF00) + (srcAddr[i + 1] & 0xFF);
+ sum = sum + wordData;
+ }
+
+ for (i = 0; i < 4; i = i + 2) {
+ wordData = ((destAddr[i] << 8) & 0xFF00) + (destAddr[i + 1] & 0xFF);
+ sum = sum + wordData;
+ }
+ sum = sum + 17 + inData.length;
+
+ while((sum >> 16) != 0) {
+ carry = (sum >> 16);
+ sum = (sum & 0xFFFF)+ carry;
+ }
+ checkSum = (short) ~((short) sum & 0xFFFF);
+ if(checkSum == 0) {
+ checkSum = (short)0xffff;
+ }
+ return checkSum;
+ }
+
+ private void setCommonOptions(DHCP pkt, DhcpInfo dhcpInfo) {
+ pkt.setOptionInt(DHCPConstants.OPT_LEASE_TIME, dhcpMgr.getDhcpLeaseTime());
+ if (dhcpMgr.getDhcpDefDomain() != null) {
+ pkt.setOptionString(DHCPConstants.OPT_DOMAIN_NAME, dhcpMgr.getDhcpDefDomain());
+ }
+ if(dhcpMgr.getDhcpLeaseTime() > 0) {
+ pkt.setOptionInt(DHCPConstants.OPT_REBINDING_TIME, dhcpMgr.getDhcpRebindingTime());
+ pkt.setOptionInt(DHCPConstants.OPT_RENEWAL_TIME, dhcpMgr.getDhcpRenewalTime());
+ }
+ SubnetUtils util = null;
+ SubnetInfo info = null;
+ util = new SubnetUtils(dhcpInfo.getCidr());
+ info = util.getInfo();
+ String gwIp = dhcpInfo.getGatewayIp();
+ List<String> dnServers = dhcpInfo.getDnsServers();
+ try {
+ /*
+ * setParameterListOptions may have initialized some of these
+ * options to maintain order. If we can't fill them, unset to avoid
+ * sending wrong information in reply.
+ */
+ if (gwIp != null) {
+ pkt.setOptionInetAddr(DHCPConstants.OPT_SERVER_IDENTIFIER, gwIp);
+ pkt.setOptionInetAddr(DHCPConstants.OPT_ROUTERS, gwIp);
+ } else {
+ pkt.unsetOption(DHCPConstants.OPT_SERVER_IDENTIFIER);
+ pkt.unsetOption(DHCPConstants.OPT_ROUTERS);
+ }
+ if (info != null) {
+ pkt.setOptionInetAddr(DHCPConstants.OPT_SUBNET_MASK, info.getNetmask());
+ pkt.setOptionInetAddr(DHCPConstants.OPT_BROADCAST_ADDRESS, info.getBroadcastAddress());
+ } else {
+ pkt.unsetOption(DHCPConstants.OPT_SUBNET_MASK);
+ pkt.unsetOption(DHCPConstants.OPT_BROADCAST_ADDRESS);
+ }
+ if ((dnServers != null) && (dnServers.size() > 0)) {
+ pkt.setOptionStrAddrs(DHCPConstants.OPT_DOMAIN_NAME_SERVERS, dnServers);
+ } else {
+ pkt.unsetOption(DHCPConstants.OPT_DOMAIN_NAME_SERVERS);
+ }
+ } catch (UnknownHostException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ private void setParameterListOptions(DHCP req, DHCP reply, DhcpInfo dhcpInfo) {
+ byte[] paramList = req.getOptionBytes(DHCPConstants.OPT_PARAMETER_REQUEST_LIST);
+ for(int i = 0; i < paramList.length; i++) {
+ switch (paramList[i]) {
+ case DHCPConstants.OPT_SUBNET_MASK:
+ case DHCPConstants.OPT_ROUTERS:
+ case DHCPConstants.OPT_SERVER_IDENTIFIER:
+ case DHCPConstants.OPT_DOMAIN_NAME_SERVERS:
+ case DHCPConstants.OPT_BROADCAST_ADDRESS:
+ case DHCPConstants.OPT_LEASE_TIME:
+ case DHCPConstants.OPT_RENEWAL_TIME:
+ case DHCPConstants.OPT_REBINDING_TIME:
+ /* These values will be filled in setCommonOptions
+ * Setting these just to preserve order as
+ * specified in PARAMETER_REQUEST_LIST.
+ */
+ reply.setOptionInt(paramList[i], 0);
+ break;
+ case DHCPConstants.OPT_DOMAIN_NAME:
+ reply.setOptionString(paramList[i], " ");
+ break;
+ case DHCPConstants.OPT_CLASSLESS_ROUTE:
+ setOptionClasslessRoute(reply, dhcpInfo);
+ break;
+ default:
+ LOG.debug("DHCP Option code {} not supported yet", paramList[i]);
+ break;
+ }
+ }
+ }
+ private void setOptionClasslessRoute(DHCP reply, DhcpInfo dhcpInfo) {
+ List<HostRoutes> hostRoutes = dhcpInfo.getHostRoutes();
+ if(hostRoutes == null) {
+ //we can't set this option, so return
+ return;
+ }
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
+ Iterator<HostRoutes> iter = hostRoutes.iterator();
+ while(iter.hasNext()) {
+ HostRoutes hostRoute = iter.next();
+ if(hostRoute.getNexthop().getIpv4Address() == null ||
+ hostRoute.getDestination().getIpv4Prefix() == null ) {
+ // we only deal with IPv4 addresses
+ return;
+ }
+ String router = hostRoute.getNexthop().getIpv4Address().getValue();
+ String dest = hostRoute.getDestination().getIpv4Prefix().getValue();
+ try {
+ result.write(convertToClasslessRouteOption(dest, router));
+ } catch (IOException | NullPointerException e) {
+ LOG.debug("Exception {}",e.getMessage());
+ }
+ }
+ if (result.size() > 0) {
+ reply.setOptionBytes(DHCPConstants.OPT_CLASSLESS_ROUTE , result.toByteArray());
+ }
+ }
+
+ protected byte[] convertToClasslessRouteOption(String dest, String router) {
+ ByteArrayOutputStream bArr = new ByteArrayOutputStream();
+ if((dest == null ||
+ router == null)) {
+ return null;
+ }
+
+ //get prefix
+ Short prefix = null;
+ String[] parts = dest.split("/");
+ if (parts.length < 2) {
+ prefix = new Short((short)0);
+ } else {
+ prefix = Short.valueOf(parts[1]);
+ }
+
+ bArr.write(prefix.byteValue());
+ SubnetUtils util = new SubnetUtils(dest);
+ SubnetInfo info = util.getInfo();
+ String strNetAddr = info.getNetworkAddress();
+ try {
+ byte[] netAddr = InetAddress.getByName(strNetAddr).getAddress();
+ //Strip any trailing 0s from netAddr
+ for(int i = 0; i < netAddr.length;i++) {
+ if(netAddr[i] != 0) {
+ bArr.write(netAddr,i,1);
+ }
+ }
+ bArr.write(InetAddress.getByName(router).getAddress());
+ } catch (IOException e) {
+ return null;
+ }
+ return bArr.toByteArray();
+ }
+
+ private boolean isPktInReasonSendtoCtrl(Class<? extends PacketInReason> pktInReason) {
+ return (pktInReason == SendToController.class);
+ }
+
+ @Override
+ public void close() throws Exception {
+ // TODO Auto-generated method stub
+ }
+
+ public void setPacketProcessingService(PacketProcessingService packetService) {
+ this.pktService = packetService;
+ }
+
+ public void setInterfaceManagerRpc(OdlInterfaceRpcService interfaceManagerRpc) {
+ LOG.trace("Registered interfaceManager successfully");;
+ this.interfaceManagerRpc = interfaceManagerRpc;
+ }
+
+ private String getInterfaceNameFromTag(long portTag) {
+ String interfaceName = null;
+ GetInterfaceFromIfIndexInput input = new GetInterfaceFromIfIndexInputBuilder().setIfIndex(new Integer((int)portTag)).build();
+ Future<RpcResult<GetInterfaceFromIfIndexOutput>> futureOutput = interfaceManagerRpc.getInterfaceFromIfIndex(input);
+ try {
+ GetInterfaceFromIfIndexOutput output = futureOutput.get().getResult();
+ interfaceName = output.getInterfaceName();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Error while retrieving the interfaceName from tag using getInterfaceFromIfIndex RPC");
+ }
+ LOG.trace("Returning interfaceName {} for tag {} form getInterfaceNameFromTag", interfaceName, portTag);
+ return interfaceName;
+ }
+
+ private org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceStateFromOperDS(String interfaceName) {
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
+ buildStateInterfaceId(interfaceName);
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateOptional =
+ MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, ifStateId, dataBroker);
+ if (!ifStateOptional.isPresent()) {
+ return null;
+ }
+
+ return ifStateOptional.get();
+ }
+
+ private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> buildStateInterfaceId(String interfaceName) {
+ InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> idBuilder =
+ InstanceIdentifier.builder(InterfacesState.class)
+ .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class,
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName));
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> id = idBuilder.build();
+ return id;
+ }
+
+ private List<Action> getEgressAction(String interfaceName, BigInteger tunnelId) {
+ List<Action> actions = null;
+ try {
+ GetEgressActionsForInterfaceInputBuilder egressAction = new GetEgressActionsForInterfaceInputBuilder().setIntfName(interfaceName);
+ if (tunnelId != null) {
+ egressAction.setTunnelKey(tunnelId.longValue());
+ }
+ Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
+ interfaceManagerRpc.getEgressActionsForInterface(egressAction.build());
+ RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to Get egress actions for interface {} returned with Errors {}", interfaceName, rpcResult.getErrors());
+ } else {
+ actions = rpcResult.getResult().getAction();
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when egress actions for interface {}", interfaceName, e);
+ }
+ return actions;
+ }
+
+ private ImmutablePair<BigInteger, String> getDpnIdPhysicalAddressFromInterfaceName(String interfaceName) {
+ ImmutablePair<BigInteger, String> pair = dhcpMgr.getInterfaceCache(interfaceName);
+ if (pair!=null && pair.getLeft() != null && pair.getRight() != null) {
+ return pair;
+ }
+ NodeConnectorId nodeConnectorId = null;
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState = getInterfaceStateFromOperDS(interfaceName);
+ if(interfaceState != null) {
+ List<String> ofportIds = interfaceState.getLowerLayerIf();
+ nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
+ }
+ BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
+ String phyAddress = interfaceState==null ? "":interfaceState.getPhysAddress().getValue();
+ pair = new ImmutablePair<BigInteger, String>(dpId, phyAddress);
+ dhcpMgr.updateInterfaceCache(interfaceName, pair);
+ return pair;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.dhcpservice;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+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.NotificationProviderService;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.vpnservice.neutronvpn.interfaces.INeutronVpnManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DhcpProvider implements BindingAwareProvider, AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DhcpProvider.class);
+ private IMdsalApiManager mdsalManager;
+ private DhcpPktHandler dhcpPktHandler;
+ private Registration packetListener = null;
+ private NotificationProviderService notificationService;
+ private DhcpManager dhcpManager;
+ private NodeListener dhcpNodeListener;
+ private INeutronVpnManager neutronVpnManager;
+ private DhcpConfigListener dhcpConfigListener;
+ private OdlInterfaceRpcService interfaceManagerRpc;
+ private DhcpInterfaceEventListener dhcpInterfaceEventListener;
+ private DhcpExternalTunnelManager dhcpExternalTunnelManager;
+ private DhcpNeutronPortListener dhcpNeutronPortListener;
+ private DhcpLogicalSwitchListener dhcpLogicalSwitchListener;
+ private DhcpUCastMacListener dhcpUCastMacListener;
+ private ItmRpcService itmRpcService;
+ private DhcpInterfaceConfigListener dhcpInterfaceConfigListener;
+ private EntityOwnershipService entityOwnershipService;
+ private DhcpDesignatedDpnListener dhcpDesignatedDpnListener;
+ private DhcpL2GatewayConnectionListener dhcpL2GatewayConnectionListener;
+
+ @Override
+ public void onSessionInitiated(ProviderContext session) {
+ LOG.info("DhcpProvider Session Initiated");
+ try {
+ final DataBroker dataBroker = session.getSALService(DataBroker.class);
+ final PacketProcessingService pktProcessingService = session.getRpcService(PacketProcessingService.class);
+ dhcpManager = new DhcpManager(dataBroker);
+ dhcpManager.setMdsalManager(mdsalManager);
+ dhcpManager.setNeutronVpnService(neutronVpnManager);
+ dhcpExternalTunnelManager = new DhcpExternalTunnelManager(dataBroker, mdsalManager, itmRpcService, entityOwnershipService);
+ dhcpPktHandler = new DhcpPktHandler(dataBroker, dhcpManager, dhcpExternalTunnelManager);
+ dhcpPktHandler.setPacketProcessingService(pktProcessingService);
+ dhcpPktHandler.setInterfaceManagerRpc(interfaceManagerRpc);
+ packetListener = notificationService.registerNotificationListener(dhcpPktHandler);
+ dhcpNodeListener = new NodeListener(dataBroker, dhcpManager, dhcpExternalTunnelManager);
+ dhcpConfigListener = new DhcpConfigListener(dataBroker, dhcpManager);
+ dhcpInterfaceEventListener = new DhcpInterfaceEventListener(dhcpManager, dataBroker, dhcpExternalTunnelManager);
+ dhcpInterfaceConfigListener = new DhcpInterfaceConfigListener(dataBroker, dhcpExternalTunnelManager);
+ dhcpLogicalSwitchListener = new DhcpLogicalSwitchListener(dhcpExternalTunnelManager, dataBroker);
+ dhcpUCastMacListener = new DhcpUCastMacListener(dhcpExternalTunnelManager, dataBroker);
+ dhcpUCastMacListener.registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
+ dhcpNeutronPortListener = new DhcpNeutronPortListener(dataBroker, dhcpExternalTunnelManager);
+ dhcpNeutronPortListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
+ dhcpDesignatedDpnListener = new DhcpDesignatedDpnListener(dhcpExternalTunnelManager, dataBroker);
+ dhcpDesignatedDpnListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
+ dhcpL2GatewayConnectionListener = new DhcpL2GatewayConnectionListener(dataBroker, dhcpExternalTunnelManager);
+ dhcpL2GatewayConnectionListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
+ } catch (Exception e) {
+ LOG.error("Error initializing services {}", e);
+ }
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ public void setNeutronVpnManager(INeutronVpnManager neutronVpnManager) {
+ this.neutronVpnManager = neutronVpnManager;
+ }
+
+ @Override
+ public void close() throws Exception {
+ if(packetListener != null) {
+ packetListener.close();
+ }
+ if(dhcpPktHandler != null) {
+ dhcpPktHandler.close();
+ }
+ if(dhcpNodeListener != null) {
+ dhcpNodeListener.close();
+ }
+ LOG.info("DhcpProvider closed");
+ }
+
+ public void setNotificationProviderService(NotificationProviderService notificationServiceDependency) {
+ this.notificationService = notificationServiceDependency;
+ }
+
+ public void setInterfaceManagerRpc(OdlInterfaceRpcService interfaceManagerRpc) {
+ this.interfaceManagerRpc = interfaceManagerRpc;
+ }
+
+ public void setItmRpcService(ItmRpcService itmRpcService) {
+ this.itmRpcService = itmRpcService;
+ }
+
+ public void setEntityOwnershipService(EntityOwnershipService entityOwnershipService) {
+ this.entityOwnershipService = entityOwnershipService;
+ }
+}
--- /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.dhcpservice;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.dhcpservice.api.DHCPMConstants;
+import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.ActionType;
+import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
+import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
+import org.opendaylight.vpnservice.mdsalutil.InstructionType;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.vpnservice.mdsalutil.packet.IPProtocols;
+import org.opendaylight.vpnservice.neutronvpn.api.utils.NeutronUtils;
+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.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+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.neutron.networks.rev150712.networks.attributes.Networks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.NetworkKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanDpnInterfaces;
+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.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class DhcpServiceUtils {
+
+ private static final Logger logger = LoggerFactory.getLogger(DhcpServiceUtils.class);
+
+ public static Interface getInterfaceFromConfigDS(String interfaceName, DataBroker dataBroker) {
+ InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
+ InstanceIdentifier<Interface> interfaceId = getInterfaceIdentifier(interfaceKey);
+ Optional<Interface> interfaceOptional = MDSALUtil.read(LogicalDatastoreType.CONFIGURATION, interfaceId, dataBroker);
+ if (!interfaceOptional.isPresent()) {
+ return null;
+ }
+ return interfaceOptional.get();
+ }
+
+ private static InstanceIdentifier<Interface> getInterfaceIdentifier(InterfaceKey interfaceKey) {
+ InstanceIdentifier.InstanceIdentifierBuilder<Interface> interfaceInstanceIdentifierBuilder =
+ InstanceIdentifier.builder(Interfaces.class).child(Interface.class, interfaceKey);
+ return interfaceInstanceIdentifierBuilder.build();
+ }
+
+ public static void setupDhcpFlowEntry(BigInteger dpId, short tableId, String vmMacAddress, int addOrRemove, IMdsalApiManager mdsalUtil) {
+ if (dpId == null || dpId.equals(DHCPMConstants.INVALID_DPID) || vmMacAddress == null) {
+ return;
+ }
+ List<MatchInfo> matches = getDhcpMatch(vmMacAddress);
+
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+
+ // Punt to controller
+ actionsInfos.add(new ActionInfo(ActionType.punt_to_controller,
+ new String[] {}));
+ instructions.add(new InstructionInfo(InstructionType.write_actions,
+ actionsInfos));
+ if (addOrRemove == NwConstants.DEL_FLOW) {
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
+ getDhcpFlowRef(dpId, tableId, vmMacAddress),
+ DHCPMConstants.DEFAULT_DHCP_FLOW_PRIORITY, "DHCP", 0, 0,
+ DHCPMConstants.COOKIE_DHCP_BASE, matches, null);
+ logger.trace("Removing DHCP Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress);
+ mdsalUtil.removeFlow(flowEntity);
+ } else {
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
+ getDhcpFlowRef(dpId, tableId, vmMacAddress),DHCPMConstants.DEFAULT_DHCP_FLOW_PRIORITY, "DHCP", 0, 0,
+ DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions);
+ logger.trace("Installing DHCP Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress);
+ mdsalUtil.installFlow(flowEntity);
+ }
+ }
+
+ private static String getDhcpFlowRef(BigInteger dpId, long tableId, String vmMacAddress) {
+ return new StringBuffer().append(DHCPMConstants.FLOWID_PREFIX)
+ .append(dpId).append(NwConstants.FLOWID_SEPARATOR)
+ .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
+ .append(vmMacAddress).toString();
+ }
+
+ public static void setupDhcpDropAction(BigInteger dpId, short tableId, String vmMacAddress, int addOrRemove, IMdsalApiManager mdsalUtil) {
+ if (dpId == null || dpId.equals(DHCPMConstants.INVALID_DPID) || vmMacAddress == null) {
+ return;
+ }
+ List<MatchInfo> matches = getDhcpMatch(vmMacAddress);
+
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos));
+ // Drop Action
+ actionsInfos.add(new ActionInfo(ActionType.drop_action,
+ new String[] {}));
+ if (addOrRemove == NwConstants.DEL_FLOW) {
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
+ getDhcpFlowRef(dpId, tableId, vmMacAddress),
+ DHCPMConstants.DEFAULT_DHCP_FLOW_PRIORITY, "DHCP", 0, 0,
+ DHCPMConstants.COOKIE_DHCP_BASE, matches, null);
+ logger.trace("Removing DHCP Drop Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress);
+ mdsalUtil.removeFlow(flowEntity);
+ } else {
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
+ getDhcpFlowRef(dpId, tableId, vmMacAddress),DHCPMConstants.DEFAULT_DHCP_FLOW_PRIORITY, "DHCP", 0, 0,
+ DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions);
+ logger.trace("Installing DHCP Drop Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress);
+ mdsalUtil.installFlow(flowEntity);
+ }
+ }
+
+ private static List<MatchInfo> getDhcpMatch(String vmMacAddress) {
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { NwConstants.ETHTYPE_IPV4 }));
+ matches.add(new MatchInfo(MatchFieldType.ip_proto,
+ new long[] { IPProtocols.UDP.intValue() }));
+ matches.add(new MatchInfo(MatchFieldType.udp_src,
+ new long[] { DHCPMConstants.dhcpClientPort }));
+ matches.add(new MatchInfo(MatchFieldType.udp_dst,
+ new long[] { DHCPMConstants.dhcpServerPort }));
+ matches.add(new MatchInfo(MatchFieldType.eth_src,
+ new String[] { vmMacAddress }));
+ return matches;
+ }
+
+ public static List<BigInteger> getListOfDpns(DataBroker broker) {
+ List<BigInteger> dpnsList = new LinkedList<BigInteger>();
+ InstanceIdentifier<Nodes> nodesInstanceIdentifier = InstanceIdentifier.builder(Nodes.class).build();
+ Optional<Nodes> nodesOptional = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, nodesInstanceIdentifier);
+ if (!nodesOptional.isPresent()) {
+ return dpnsList;
+ }
+ Nodes nodes = nodesOptional.get();
+ List<Node> nodeList = nodes.getNode();
+ for (Node node : nodeList) {
+ NodeId nodeId = node.getId();
+ if (nodeId == null) {
+ continue;
+ }
+ BigInteger dpnId = MDSALUtil.getDpnIdFromNodeName(nodeId);
+ dpnsList.add(dpnId);
+ }
+ return dpnsList;
+ }
+
+ public static List<BigInteger> getDpnsForElan(String elanInstanceName, DataBroker broker) {
+ List<BigInteger> elanDpns = new LinkedList<BigInteger>();
+ InstanceIdentifier<ElanDpnInterfacesList> elanDpnInstanceIdentifier = InstanceIdentifier.builder(ElanDpnInterfaces.class).child(ElanDpnInterfacesList.class, new ElanDpnInterfacesListKey(elanInstanceName)).build();
+ Optional<ElanDpnInterfacesList> elanDpnOptional = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, elanDpnInstanceIdentifier);
+ if (elanDpnOptional.isPresent()) {
+ List<DpnInterfaces> dpns = elanDpnOptional.get().getDpnInterfaces();
+ for (DpnInterfaces dpnInterfaces : dpns) {
+ elanDpns.add(dpnInterfaces.getDpId());
+ }
+ }
+ return elanDpns;
+ }
+
+ public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceFromOperationalDS(String interfaceName, DataBroker dataBroker) {
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey interfaceKey = new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName);
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceId = InstanceIdentifier.builder(InterfacesState.class).child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class, interfaceKey).build();
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceOptional = MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, interfaceId, dataBroker);
+ if (!interfaceOptional.isPresent()) {
+ return null;
+ }
+ return interfaceOptional.get();
+ }
+
+
+ public static String getSegmentationId(Uuid networkId, DataBroker broker) {
+ InstanceIdentifier<Network> inst = InstanceIdentifier.create(Neutron.class).child(Networks.class).child
+ (Network.class, new NetworkKey(networkId));
+ Optional<Network> optionalNetwork = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, inst);
+ if (!optionalNetwork.isPresent()) {
+ return null;
+ }
+ Network network = optionalNetwork.get();
+ String segmentationId = NeutronUtils.getSegmentationIdFromNeutronNetwork(network);
+ return segmentationId;
+ }
+
+ public static String getNodeIdFromDpnId(BigInteger dpnId) {
+ return MDSALUtil.NODE_PREFIX + MDSALUtil.SEPARATOR + dpnId.toString();
+ }
+
+ public static String getTrunkPortMacAddress(String parentRefName,
+ DataBroker broker) {
+ InstanceIdentifier<Port> portInstanceIdentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class);
+ Optional<Port> trunkPort = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, portInstanceIdentifier);
+ if (!trunkPort.isPresent()) {
+ logger.warn("Trunk port {} not available for sub-port", parentRefName);
+ return null;
+ }
+ return trunkPort.get().getMacAddress();
+ }
+}
\ 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.dhcpservice;
+
+import java.math.BigInteger;
+
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
+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.elanmanager.utils.ElanL2GwCacheUtils;
+import org.opendaylight.vpnservice.datastoreutils.AsyncClusteredDataChangeListenerBase;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class DhcpUCastMacListener extends AsyncClusteredDataChangeListenerBase<LocalUcastMacs, DhcpUCastMacListener> implements AutoCloseable {
+
+ private static final Logger logger = LoggerFactory.getLogger(DhcpUCastMacListener.class);
+ private DataBroker broker;
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private DhcpExternalTunnelManager dhcpExternalTunnelManager;
+
+ public DhcpUCastMacListener(DhcpExternalTunnelManager dhcpManager, DataBroker dataBroker) {
+ super(LocalUcastMacs.class, DhcpUCastMacListener.class);
+ this.broker = dataBroker;
+ this.dhcpExternalTunnelManager = dhcpManager;
+ }
+
+ @Override
+ protected InstanceIdentifier<LocalUcastMacs> getWildCardPath() {
+ return InstanceIdentifier.create(NetworkTopology.class).child(Topology.class).child(Node.class)
+ .augmentation(HwvtepGlobalAugmentation.class).child(LocalUcastMacs.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;
+ }
+ logger.info("DhcpUCastMacListener Closed");
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<LocalUcastMacs> identifier,
+ LocalUcastMacs del) {
+ // Flow removal for table 18 is handled in Neutron Port delete.
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<LocalUcastMacs> identifier,
+ LocalUcastMacs original, LocalUcastMacs update) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<LocalUcastMacs> identifier,
+ LocalUcastMacs add) {
+ NodeId torNodeId = identifier.firstKeyOf(Node.class).getNodeId();
+ InstanceIdentifier<LogicalSwitches> logicalSwitchRef = (InstanceIdentifier<LogicalSwitches>) add.getLogicalSwitchRef().getValue();
+ Optional<LogicalSwitches> logicalSwitchOptional = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, logicalSwitchRef);
+ if ( !logicalSwitchOptional.isPresent() ) {
+ logger.error("Logical Switch ref doesn't have data {}", logicalSwitchRef);
+ return;
+ }
+ LogicalSwitches logicalSwitch = logicalSwitchOptional.get();
+ String elanInstanceName = logicalSwitch.getHwvtepNodeName().getValue();
+ String macAddress = add.getMacEntryKey().getValue();
+ BigInteger vni = new BigInteger(logicalSwitch.getTunnelKey());
+ Port port = dhcpExternalTunnelManager.readVniMacToPortCache(vni, macAddress);
+ if (port == null) {
+ logger.trace("No neutron port created for macAddress {}, tunnelKey {}", macAddress, vni);
+ return;
+ }
+ L2GatewayDevice device = ElanL2GwCacheUtils.getL2GatewayDeviceFromCache(elanInstanceName, torNodeId.getValue());
+ if (device == null) {
+ logger.error("Logical Switch Device with name {} is not present in L2GWCONN cache", elanInstanceName);
+ return;
+ }
+ IpAddress tunnelIp = device.getTunnelIp();
+ BigInteger designatedDpnId = dhcpExternalTunnelManager.readDesignatedSwitchesForExternalTunnel(tunnelIp, elanInstanceName);
+ dhcpExternalTunnelManager.installDhcpFlowsForVms(tunnelIp, elanInstanceName, DhcpServiceUtils.getListOfDpns(broker), designatedDpnId, macAddress);
+ }
+
+ @Override
+ protected ClusteredDataChangeListener getDataChangeListener() {
+ return DhcpUCastMacListener.this;
+ }
+
+ @Override
+ protected DataChangeScope getDataChangeScope() {
+ return DataChangeScope.SUBTREE;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.dhcpservice;
+
+import java.math.BigInteger;
+import java.util.List;
+
+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.dhcpservice.api.DHCPMConstants;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+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;
+
+public class NodeListener extends AbstractDataChangeListener<Node> implements AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NodeListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private DhcpManager dhcpManager;
+ private DhcpExternalTunnelManager dhcpExternalTunnelManager;
+
+ public NodeListener(final DataBroker db, final DhcpManager dhcpMgr, final DhcpExternalTunnelManager dhcpExternalTunnelManager) {
+ super(Node.class);
+ broker = db;
+ dhcpManager = dhcpMgr;
+ this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
+ registerListener(db);
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), NodeListener.this, AsyncDataBroker.DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("NodeListener: DataChange listener registration fail!", e);
+ throw new IllegalStateException("NodeListener: 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) {
+ NodeId nodeId = del.getId();
+ BigInteger dpnId = MDSALUtil.getDpnIdFromNodeName(nodeId);
+ List<BigInteger> listOfDpns = DhcpServiceUtils.getListOfDpns(broker);
+ dhcpExternalTunnelManager.handleDesignatedDpnDown(dpnId, listOfDpns);
+ }
+
+ @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(":");
+ if(node.length < 2) {
+ LOG.warn("Unexpected nodeId {}", nodeId.getValue());
+ return;
+ }
+ BigInteger dpId = new BigInteger(node[1]);
+ dhcpManager.setupTableMissForDhcpTable(dpId);
+ dhcpExternalTunnelManager.installDhcpDropActionOnDpn(dpId);
+ List<BigInteger> listOfDpns = DhcpServiceUtils.getListOfDpns(broker);
+ dhcpExternalTunnelManager.handleDesignatedDpnDown(DHCPMConstants.INVALID_DPID, listOfDpns);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up NodeListener.", e);
+ }
+ listenerRegistration = null;
+ //ToDo: Should we delete DHCP flows when we are closed?
+ }
+ LOG.debug("Node Listener Closed");
+ }
+}
--- /dev/null
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.impl.rev150710;
+
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.vpnservice.dhcpservice.DhcpProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+
+public class DhcpServiceImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.impl.rev150710.AbstractDhcpServiceImplModule {
+ public DhcpServiceImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public DhcpServiceImplModule(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.dhcpservice.impl.rev150710.DhcpServiceImplModule 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();
+ DhcpProvider dhcpProvider = new DhcpProvider();
+ dhcpProvider.setNotificationProviderService(getNotificationServiceDependency());
+ dhcpProvider.setMdsalManager(getMdsalutilDependency());
+ dhcpProvider.setNeutronVpnManager(getNeutronvpnDependency());
+ dhcpProvider.setInterfaceManagerRpc(rpcregistryDependency.getRpcService(OdlInterfaceRpcService.class));
+ dhcpProvider.setItmRpcService(rpcregistryDependency.getRpcService(ItmRpcService.class));
+ dhcpProvider.setEntityOwnershipService(getEntityOwnershipServiceDependency());
+ getBrokerDependency().registerProvider(dhcpProvider);
+ return dhcpProvider;
+ }
+
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: dhcpservice-impl yang module local name: dhcpservice-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Sat Jul 11 21:38:25 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.dhcpservice.impl.rev150710;
+public class DhcpServiceImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.impl.rev150710.AbstractDhcpServiceImplModuleFactory {
+
+}
--- /dev/null
+module dhcpservice-impl {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:dhcpservice:impl";
+ prefix "dhcpservice-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 odl-mdsalutil { prefix odl-mdsal; revision-date 2015-04-10;}
+ import neutronvpn-api { prefix nvpn; revision-date 2015-08-12;}
+ import opendaylight-entity-ownership-service { prefix eos; revision-date 2015-08-10;}
+
+ description
+ "Service definition for dhcpservice project";
+
+ revision "2015-07-10" {
+ description
+ "Initial revision";
+ }
+
+ identity dhcpservice-impl {
+ base config:module-type;
+ config:java-name-prefix DhcpServiceImpl;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case dhcpservice-impl {
+ when "/config:modules/config:module/config:type = 'dhcpservice-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 notification-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-notification-service;
+ }
+ }
+ }
+
+ container mdsalutil {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity odl-mdsal:odl-mdsalutil;
+ }
+ }
+ }
+
+ container neutronvpn {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity nvpn:neutronvpn-api;
+ }
+ }
+ }
+
+ container entity-ownership-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity eos:entity-ownership-service;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>dhcpservice-aggregator</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <name>dhcpservice</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>dhcpservice-api</module>
+ <module>dhcpservice-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>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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.controller</groupId>
+ <artifactId>karaf-parent</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>vpnservice-karaf</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <name>${project.artifactId}</name>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <properties>
+ <!-- <karaf.localFeature>odl-vpnservice-core</karaf.localFeature> -->
+ </properties>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>vpnservice-artifacts</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <!-- scope is compile so all features (there is only one) are installed
+ into startup.properties and the feature repo itself is not installed -->
+ <groupId>org.apache.karaf.features</groupId>
+ <artifactId>framework</artifactId>
+ <type>kar</type>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>vpnservice-features</artifactId>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <!-- DO NOT deploy the karaf artifact -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-deploy-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
--- /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.3.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>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>neutronvpn-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </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
+/*
+ * 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.utils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.vpnservice.utils.cache.CacheUtil;
+
+public class ElanL2GwCacheUtils {
+ private static final ConcurrentHashMap<String, L2GatewayDevice> EMPTY_MAP = new ConcurrentHashMap<String, L2GatewayDevice>();
+ public static final String L2GATEWAY_CONN_CACHE_NAME = "L2GWCONN";
+
+ public static void createElanL2GwDeviceCache() {
+ if (CacheUtil.getCache(ElanL2GwCacheUtils.L2GATEWAY_CONN_CACHE_NAME) == null) {
+ CacheUtil.createCache(ElanL2GwCacheUtils.L2GATEWAY_CONN_CACHE_NAME);
+ }
+ }
+
+ public static void addL2GatewayDeviceToCache(String elanName, L2GatewayDevice l2GwDevice) {
+ ConcurrentMap<String, ConcurrentMap<String, L2GatewayDevice>> cachedMap =
+ (ConcurrentMap<String, ConcurrentMap<String, L2GatewayDevice>>) CacheUtil.getCache(
+ ElanL2GwCacheUtils.L2GATEWAY_CONN_CACHE_NAME);
+ ConcurrentMap<String, L2GatewayDevice> deviceMap = cachedMap.get(elanName);
+ if (deviceMap == null) {
+ synchronized(ElanL2GwCacheUtils.class) {
+ deviceMap = cachedMap.get(elanName);
+ if (deviceMap == null) {
+ deviceMap = new ConcurrentHashMap<String, L2GatewayDevice>();
+ cachedMap.put(elanName, deviceMap);
+ }
+ }
+ }
+ deviceMap.put(l2GwDevice.getHwvtepNodeId(), l2GwDevice);
+ }
+
+ public static void removeL2GatewayDeviceFromAllElanCache(String deviceName) {
+ ConcurrentMap<String, ConcurrentMap<String, L2GatewayDevice>> cachedMap =
+ (ConcurrentMap<String, ConcurrentMap<String, L2GatewayDevice>>) CacheUtil.getCache(
+ ElanL2GwCacheUtils.L2GATEWAY_CONN_CACHE_NAME);
+ for (String elanName : cachedMap.keySet()) {
+ ConcurrentMap<String, L2GatewayDevice> deviceMap = cachedMap.get(elanName);
+ if (deviceMap != null) {
+ deviceMap.remove(deviceName);
+ }
+ }
+ }
+
+
+ public static L2GatewayDevice removeL2GatewayDeviceFromCache(String elanName, String l2gwDeviceNodeId) {
+ ConcurrentMap<String, ConcurrentMap<String, L2GatewayDevice>> cachedMap =
+ (ConcurrentMap<String, ConcurrentMap<String, L2GatewayDevice>>) CacheUtil.getCache(
+ ElanL2GwCacheUtils.L2GATEWAY_CONN_CACHE_NAME);
+ ConcurrentMap<String, L2GatewayDevice> deviceMap = cachedMap.get(elanName);
+ if (deviceMap != null) {
+ L2GatewayDevice device = deviceMap.remove(l2gwDeviceNodeId);
+ return device;
+ } else {
+ return null;
+ }
+ }
+
+ public static L2GatewayDevice getL2GatewayDeviceFromCache(String elanName, String l2gwDeviceNodeId) {
+ ConcurrentMap<String, ConcurrentMap<String, L2GatewayDevice>> cachedMap =
+ (ConcurrentMap<String, ConcurrentMap<String, L2GatewayDevice>>) CacheUtil.getCache(
+ ElanL2GwCacheUtils.L2GATEWAY_CONN_CACHE_NAME);
+ ConcurrentMap<String, L2GatewayDevice> deviceMap = cachedMap.get(elanName);
+ if (deviceMap != null) {
+ return deviceMap.get(l2gwDeviceNodeId);
+ } else {
+ return null;
+ }
+ }
+
+ public static ConcurrentMap<String, L2GatewayDevice> getInvolvedL2GwDevices(String elanName) {
+ ConcurrentMap<String, ConcurrentMap<String, L2GatewayDevice>> cachedMap = (ConcurrentMap<String, ConcurrentMap<String, L2GatewayDevice>>) CacheUtil
+ .getCache(ElanL2GwCacheUtils.L2GATEWAY_CONN_CACHE_NAME);
+ ConcurrentMap<String, L2GatewayDevice> result = cachedMap.get(elanName);
+ if (result == null) {
+ result = EMPTY_MAP;
+ }
+ return result;
+ }
+
+ public static List<L2GatewayDevice> getAllElanDevicesFromCache() {
+ List<String> l2GwsList = new ArrayList<>();
+ ConcurrentMap<String, ConcurrentMap<String, L2GatewayDevice>> cachedMap =
+ (ConcurrentMap<String, ConcurrentMap<String, L2GatewayDevice>>) CacheUtil.getCache(
+ ElanL2GwCacheUtils.L2GATEWAY_CONN_CACHE_NAME);
+ if (cachedMap == null || cachedMap.isEmpty()) {
+ return null;
+ }
+
+ List<L2GatewayDevice> l2GwDevices = new ArrayList<L2GatewayDevice>();
+ for (ConcurrentMap<String, L2GatewayDevice> l2gwDevices : cachedMap.values())
+ {
+ for (L2GatewayDevice l2gwDevice : l2gwDevices.values() ) {
+ l2GwDevices.add(l2gwDevice);
+ }
+ }
+
+ return l2GwDevices;
+ }
+
+}
--- /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-inet-types {
+ prefix inet;
+ revision-date "2010-09-24";
+ }
+ 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 vni {
+ type uint32;
+ description "Optional. Network identifier. It's mandatory when there are external devices
+ participating in the ELAN";
+ }
+ 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.3.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>
+
+ <properties>
+ <powermock.version>1.6.4</powermock.version>
+ <mockitoall.version>1.10.19</mockitoall.version>
+ </properties>
+
+ <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.vpnservice</groupId>
+ <artifactId>neutronvpn-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.ovsdb</groupId>
+ <artifactId>hwvtepsouthbound-api</artifactId>
+ <version>${vpns.ovsdb.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.neutron</groupId>
+ <artifactId>model</artifactId>
+ <version>${neutron.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.console</artifactId>
+ <version>3.0.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>interfacemgr-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>dhcpservice-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+
+ <!-- Only for unit-test -->
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <version>${mockitoall.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>${powermock.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${powermock.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <version>${mdsal.version}</version>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <scope>test</scope>
+ </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:params:xml:ns:yang:controller:config:distributed-entity-ownership-service?module=distributed-entity-ownership-service&revision=2015-08-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>
+ <entity-ownership-service>
+ <type xmlns:entity-ownership="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:entity-ownership-service">entity-ownership:entity-ownership-service</type>
+ <name>entity-ownership-service</name>
+ </entity-ownership-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.cli.l2gw;
+
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.elanmanager.utils.ElanL2GwCacheUtils;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.utils.L2GatewayCacheUtils;
+import org.opendaylight.vpnservice.utils.cache.CacheUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Command(scope = "l2gw", name = "show-cache", description = "display l2gateways cache")
+public class L2GwUtilsCacheCli extends OsgiCommandSupport {
+ private static final Logger logger = LoggerFactory.getLogger(L2GwUtilsCacheCli.class);
+
+ private static final String DEMARCATION = "=================================";
+
+ @Option(name = "-cache", aliases = {"--cache"}, description = "cache name",
+ required = false, multiValued = false)
+ String cacheName = null;
+
+ @Option(name = "-elan", aliases = {"--elan"}, description = "elan name",
+ required = false, multiValued = false)
+ String elanName;
+
+ @Override
+ protected Object doExecute() {
+ try {
+ if (cacheName == null) {
+ System.out.println("Available caches");
+ System.out.println(ElanL2GwCacheUtils.L2GATEWAY_CONN_CACHE_NAME);
+ System.out.println(L2GatewayCacheUtils.L2GATEWAY_CACHE_NAME);
+ return null;
+ }
+ switch (cacheName) {
+ case ElanL2GwCacheUtils.L2GATEWAY_CONN_CACHE_NAME:
+ dumpElanL2GwCache();
+ break;
+ case L2GatewayCacheUtils.L2GATEWAY_CACHE_NAME:
+ dumpL2GwCache();
+ break;
+ }
+ } catch (Exception e) {
+ }
+
+ return null;
+ }
+
+ private void dumpL2GwCache() {
+ ConcurrentMap<String, L2GatewayDevice> devices = (ConcurrentMap<String, L2GatewayDevice>) CacheUtil
+ .getCache(L2GatewayCacheUtils.L2GATEWAY_CACHE_NAME);
+ if (devices == null) {
+ System.out.println("no devices are present in cache");
+ return;
+ }
+ for (String deviceName : devices.keySet()) {
+ System.out.println("device "+ devices.get(deviceName));
+ }
+ }
+
+ private void dumpElanL2GwCache() {
+ if (elanName == null) {
+ ConcurrentMap<String, ConcurrentMap<String, L2GatewayDevice>> cache =
+ (ConcurrentMap<String, ConcurrentMap<String, L2GatewayDevice>>) CacheUtil.getCache(
+ cacheName);
+ if (cache == null) {
+ System.out.println("no devices are present in elan cache");
+ }
+ for (String elan : cache.keySet()) {
+ print(elan, cache.get(elan));
+ System.out.println(DEMARCATION);
+ System.out.println(DEMARCATION);
+ }
+ return;
+ }
+ ConcurrentMap<String, L2GatewayDevice> elanDevices = ElanL2GwCacheUtils
+ .getInvolvedL2GwDevices(elanName);
+ print(elanName, elanDevices);
+ }
+
+ private void print(String elan,
+ ConcurrentMap<String, L2GatewayDevice> devices) {
+ System.out.println("Elan name : "+elan);
+ System.out.println("No of devices in elan "+devices.keySet().size());
+ for (String deviceName : devices.keySet()) {
+ System.out.println("device "+ devices.get(deviceName));
+ }
+ }
+}
--- /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 java.util.List;
+import java.util.concurrent.Callable;
+
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
+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.elanmanager.utils.ElanL2GwCacheUtils;
+import org.opendaylight.vpnservice.datastoreutils.AsyncClusteredDataChangeListenerBase;
+import org.opendaylight.vpnservice.elan.l2gw.utils.ElanL2GatewayMulticastUtils;
+import org.opendaylight.vpnservice.elan.l2gw.utils.ElanL2GatewayUtils;
+import org.opendaylight.vpnservice.elan.utils.ElanClusterUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanDpnInterfaces;
+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.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class ElanDpnInterfaceClusteredListener
+ extends AsyncClusteredDataChangeListenerBase<DpnInterfaces, ElanDpnInterfaceClusteredListener>
+ implements AutoCloseable {
+ private DataBroker broker;
+ private ElanInterfaceManager elanInterfaceManager;
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+
+ private static final Logger LOG = LoggerFactory.getLogger(ElanDpnInterfaceClusteredListener.class);
+
+ public ElanDpnInterfaceClusteredListener(final DataBroker db, final ElanInterfaceManager ifManager) {
+ super(DpnInterfaces.class, ElanDpnInterfaceClusteredListener.class);
+ broker = db;
+ elanInterfaceManager = ifManager;
+ registerListener(db);
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = broker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), ElanDpnInterfaceClusteredListener.this, AsyncDataBroker.DataChangeScope.BASE);
+ } catch (final Exception e) {
+ LOG.error("DpnInterfaces DataChange listener registration fail!", e);
+ }
+ }
+
+ @Override
+ public InstanceIdentifier<DpnInterfaces> getWildCardPath() {
+ return InstanceIdentifier.builder(ElanDpnInterfaces.class).child(ElanDpnInterfacesList.class)
+ .child(DpnInterfaces.class).build();
+ }
+
+ @Override
+ protected ClusteredDataChangeListener getDataChangeListener() {
+ return ElanDpnInterfaceClusteredListener.this;
+ }
+
+ @Override
+ protected AsyncDataBroker.DataChangeScope getDataChangeScope() {
+ return AsyncDataBroker.DataChangeScope.BASE;
+ }
+
+ void handleUpdate(InstanceIdentifier<DpnInterfaces> id, DpnInterfaces dpnInterfaces) {
+ final String elanName = getElanName(id);
+ if (ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName).isEmpty()) {
+ LOG.debug("dpnInterface updation, no external l2 devices to update for elan {} with Dp Id:", elanName,
+ dpnInterfaces.getDpId());
+ return;
+ }
+ ElanClusterUtils.runOnlyInLeaderNode(elanName, "updating mcast mac upon tunnel event",
+ new Callable<List<ListenableFuture<Void>>>() {
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ return Lists.newArrayList(
+ ElanL2GatewayMulticastUtils.updateRemoteMcastMacOnElanL2GwDevices(elanName));
+ }
+ });
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<DpnInterfaces> identifier, final DpnInterfaces dpnInterfaces) {
+ // this is the last dpn interface on this elan
+ final String elanName = getElanName(identifier);
+ LOG.debug("Received ElanDpnInterface removed for for elan {} with Dp Id ", elanName,
+ dpnInterfaces.getDpId());
+
+ if (ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName).isEmpty()) {
+ LOG.debug("dpnInterface removed, no external l2 devices to update for elan {} with Dp Id:", elanName,
+ dpnInterfaces.getDpId());
+ return;
+ }
+ ElanClusterUtils.runOnlyInLeaderNode(elanName, "handling ElanDpnInterface removed",
+ new Callable<List<ListenableFuture<Void>>>() {
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ // deleting Elan L2Gw Devices UcastLocalMacs From Dpn
+ ElanL2GatewayUtils.deleteElanL2GwDevicesUcastLocalMacsFromDpn(elanName,
+ dpnInterfaces.getDpId());
+ // updating remote mcast mac on l2gw devices
+ return Lists.newArrayList(
+ ElanL2GatewayMulticastUtils.updateRemoteMcastMacOnElanL2GwDevices(elanName));
+ }
+ });
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<DpnInterfaces> identifier, DpnInterfaces original,
+ final DpnInterfaces dpnInterfaces) {
+ LOG.debug("dpninterfaces update fired new size {}", dpnInterfaces.getInterfaces().size());
+ if (dpnInterfaces.getInterfaces().size() == 0) {
+ LOG.debug("dpninterfaces last dpn interface on this elan {} ", dpnInterfaces.getKey());
+ // this is the last dpn interface on this elan
+ handleUpdate(identifier, dpnInterfaces);
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<DpnInterfaces> identifier, final DpnInterfaces dpnInterfaces) {
+ if (dpnInterfaces.getInterfaces().size() == 1) {
+ LOG.debug("dpninterfaces first dpn interface on this elan {} {} ", dpnInterfaces.getKey(),
+ dpnInterfaces.getInterfaces().get(0));
+ // this is the first dpn interface on this elan
+ handleUpdate(identifier, dpnInterfaces);
+ }
+ }
+
+ /**
+ * @param identifier
+ * @return
+ */
+ private String getElanName(InstanceIdentifier<DpnInterfaces> identifier) {
+ return identifier.firstKeyOf(ElanDpnInterfacesList.class).getElanInstanceName();
+ }
+}
--- /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 static final Logger logger = LoggerFactory.getLogger(ElanForwardingEntriesHandler.class);
+ private DataBroker broker;
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+
+ public ElanForwardingEntriesHandler(DataBroker db){
+ super(ElanInterface.class);
+ this.broker = db;
+ }
+
+ 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);
+ deleteElanInterfaceForwardingTablesList(interfaceInfo.getInterfaceName(), macEntry);
+ 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.interfacemgr.globals.InterfaceInfo;
+import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
+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 IInterfaceManager interfaceManager;
+
+ 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 setInterfaceManager(IInterfaceManager interfaceManager) {
+ this.interfaceManager = interfaceManager;
+ }
+
+
+ /**
+ * Starts listening for changes in elan.yang:elan-instance container
+ */
+ 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 deletedElan) {
+ logger.trace("Remove ElanInstance - Key: {}, value: {}", identifier, deletedElan);
+ String elanName = deletedElan.getElanInstanceName();
+ //check the elan Instance present in the Operational DataStore
+ Elan existingElan = ElanUtils.getElanByName(elanName);
+ long elanTag = deletedElan.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);
+ InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(elanInterfaceName);
+ elanInterfaceManager.removeElanInterface(deletedElan, elanInterfaceName, interfaceInfo);
+ 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) {
+ Long existingElanTag = original.getElanTag();
+ if (existingElanTag != null && existingElanTag == update.getElanTag()) {
+ return;
+ } else if (update.getElanTag() == null) {
+ // update the elan-Instance with new properties
+ 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 java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
+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 com.google.common.util.concurrent.ListenableFuture;
+
+public class ElanInterfaceAddWorker implements Callable<List<ListenableFuture<Void>>> {
+ private String key;
+ private ElanInterface elanInterface;
+ private ElanInstance elanInstance;
+ private InterfaceInfo interfaceInfo;
+ private ElanInterfaceManager dataChangeListener;
+
+ public ElanInterfaceAddWorker(String key, ElanInterface elanInterface, InterfaceInfo interfaceInfo,
+ ElanInstance elanInstance, ElanInterfaceManager dataChangeListener) {
+ super();
+ this.key = key;
+ this.elanInterface = elanInterface;
+ this.interfaceInfo = interfaceInfo;
+ this.elanInstance = elanInstance;
+ this.dataChangeListener = dataChangeListener;
+ }
+
+ @Override
+ public String toString() {
+ return "ElanInterfaceAddWorker [key=" + key + ", elanInterface=" + elanInterface + ", elanInstance="
+ + elanInstance + ", interfaceInfo=" + interfaceInfo + "]";
+ }
+
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ dataChangeListener.addElanInterface(elanInterface, interfaceInfo, elanInstance);
+ return futures;
+ }
+
+
+
+}
--- /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 java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.commons.lang3.StringUtils;
+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.elanmanager.utils.ElanL2GwCacheUtils;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.elan.l2gw.utils.ElanL2GatewayUtils;
+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.globals.ITMConstants;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.ActionType;
+import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
+import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
+import org.opendaylight.vpnservice.mdsalutil.InstructionType;
+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.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+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.list.Action;
+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.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+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.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.OdlInterfaceRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+/**
+ * Class in charge of handling creations, modifications and removals of ElanInterfaces.
+ *
+ * @see org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.interfaces.ElanInterface
+ *
+ */
+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 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;
+ }
+
+ @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());
+ InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(interfaceName);
+ String elanInstanceName = elanInfo.getElanInstanceName();
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ ElanInterfaceRemoveWorker configWorker = new ElanInterfaceRemoveWorker(elanInstanceName, elanInfo, interfaceName, interfaceInfo, this);
+ coordinator.enqueueJob(elanInstanceName, configWorker, ElanConstants.JOB_MAX_RETRIES);
+ }
+
+ public void removeElanInterface(ElanInstance elanInfo, String interfaceName, InterfaceInfo interfaceInfo) {
+ String elanName = elanInfo.getElanInstanceName();
+ if (interfaceInfo == null) {
+ // Interface does not exist in ConfigDS, so lets remove everything about that interface related to Elan
+ 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()));
+ } else {
+ Elan updateElanState = new ElanBuilder().setElanInterfaces(elanInterfaces).setName(elanName).setKey(new ElanKey(elanName)).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanInstanceOperationalDataPath(elanName), updateElanState);
+ }
+ } else {
+ removeElanInterface(elanInfo, interfaceInfo);
+ unbindService(elanInfo, interfaceName);
+ }
+ }
+
+ private void removeElanInterface(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
+
+ BigInteger dpId = interfaceInfo.getDpId();
+ String elanName = elanInfo.getElanInstanceName();
+ long elanTag = elanInfo.getElanTag();
+ 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<PhysAddress> macAddresses = new ArrayList<PhysAddress>();
+ List<MacEntry> existingMacEntries = existingElanInterface.get().getMacEntry();
+ List<MacEntry> macEntries = new ArrayList<>();
+ if (existingMacEntries != null && !existingMacEntries.isEmpty()) {
+ macEntries.addAll(existingMacEntries);
+ }
+ if(!macEntries.isEmpty()) {
+ for (MacEntry macEntry : macEntries) {
+ logger.debug("removing the mac-entry:{} present on elanInterface:{}", macEntry.getMacAddress().getValue(), interfaceName);
+ elanForwardingEntriesHandler.deleteElanInterfaceForwardingEntries(elanInfo, interfaceInfo, macEntry);
+ macAddresses.add(macEntry.getMacAddress());
+ }
+
+ // Removing all those MACs from External Devices belonging to this ELAN
+ if ( elanInfo.getVni() != null && elanInfo.getVni() != 0 ) {
+ ElanL2GatewayUtils.removeMacsFromElanExternalDevices(elanInfo, macAddresses);
+ }
+ }
+ }
+ /*
+ *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, elanTag);
+ break;
+ }
+ }
+ }
+ } else {
+ removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId, interfaceName, elanTag);
+ }
+
+ removeStaticELanFlows(elanInfo, interfaceInfo);
+ ElanUtils.delete(broker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
+ 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.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, long elanTag) {
+ DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
+ if(dpnInterfaces != null) {
+ List<String> interfaceLists = dpnInterfaces.getInterfaces();
+ interfaceLists.remove(interfaceName);
+
+ if (interfaceLists == null || interfaceLists.isEmpty()) {
+ deleteAllRemoteMacsInADpn(elanName, dpId, elanTag);
+ deleteElanDpnInterface(elanName, dpId);
+ } else {
+ updateElanDpnInterfacesList(elanName, dpId, interfaceLists);
+ }
+ }
+ }
+
+ private void deleteAllRemoteMacsInADpn(String elanName, BigInteger dpId, long elanTag) {
+ List<DpnInterfaces> dpnInterfaces = ElanUtils.getInvolvedDpnsInElan(elanName);
+ for (DpnInterfaces dpnInterface : dpnInterfaces) {
+ BigInteger currentDpId = dpnInterface.getDpId();
+ if (!currentDpId.equals(dpId)) {
+ for (String elanInterface : dpnInterface.getInterfaces()) {
+ ElanInterfaceMac macs = ElanUtils.getElanInterfaceMacByInterfaceName(elanInterface);
+ if (macs == null) {
+ continue;
+ }
+ for (MacEntry mac : macs.getMacEntry())
+ mdsalManager.removeFlow(dpId, MDSALUtil.buildFlow(ElanConstants.ELAN_DMAC_TABLE,
+ ElanUtils.getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, dpId, currentDpId, mac.getMacAddress().getValue(), elanTag)));
+ }
+ }
+ }
+ }
+
+ @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);
+ if (interfaceInfo == null) {
+ logger.warn("Interface {} is removed from Interface Oper DS due to port down ", interfaceName);
+ return;
+ }
+ 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;
+ }
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ ElanInterfaceAddWorker addWorker = new ElanInterfaceAddWorker(elanInstanceName, elanInterfaceAdded,
+ interfaceInfo, elanInstance, this);
+ coordinator.enqueueJob(elanInstanceName, addWorker, ElanConstants.JOB_MAX_RETRIES);
+ }
+
+ 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 programRemoteDmacFlow(ElanInstance elanInstance, InterfaceInfo interfaceInfo){
+ ElanDpnInterfacesList elanDpnInterfacesList = ElanUtils.getElanDpnInterfacesList(elanInstance.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(interfaceInfo.getDpId(), remoteInterface.getDpId(),
+ remoteInterface.getInterfaceTag(),
+ elanInstance.getElanTag(),
+ physAddress.getValue(),
+ elanInstance.getElanInstanceName());
+ }
+ }
+ }
+ }
+ }
+
+ void addElanInterface(ElanInterface elanInterface, InterfaceInfo interfaceInfo, ElanInstance elanInstance) {
+ Preconditions.checkNotNull(elanInstance, "elanInstance cannot be null");
+ Preconditions.checkNotNull(interfaceInfo, "interfaceInfo cannot be null");
+ Preconditions.checkNotNull(elanInterface, "elanInterface cannot be null");
+
+ String interfaceName = elanInterface.getName();
+ String elanInstanceName = elanInterface.getElanInstanceName();
+ List<PhysAddress> staticMacAddresses = elanInterface.getStaticMacEntries();
+
+ Elan elanInfo = ElanUtils.getElanByName(elanInstanceName);
+ if(elanInfo == null) {
+ ElanUtils.updateOperationalDataStore(broker, idManager, elanInstance);
+ }
+
+ // Specific actions to the DPN where the ElanInterface has been added, for example, programming the
+ // External tunnel table if needed or adding the ElanInterface to the DpnInterfaces in the operational DS.
+ BigInteger dpId = ( interfaceInfo != null ) ? dpId = interfaceInfo.getDpId() : null;
+ 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()) {
+ // ELAN's 1st ElanInterface added to this DPN
+ createElanInterfacesList(elanInstanceName, interfaceName, dpId);
+ /*
+ * Install remote DMAC flow.
+ * This is required since this DPN is added later to the elan instance
+ * and remote DMACs of other interfaces in this elan instance are not present in the current dpn.
+ */
+ programRemoteDmacFlow(elanInstance, interfaceInfo);
+ // The 1st ElanInterface in a DPN must program the Ext Tunnel table, but only if Elan has VNI
+ if ( elanInstance.getVni() != null && elanInstance.getVni().longValue() != 0 ) {
+ setExternalTunnelTable(dpId, elanInstance);
+ }
+ ElanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance);
+ } else {
+ List<String> elanInterfaces = existingElanDpnInterfaces.get().getInterfaces();
+ elanInterfaces.add(interfaceName);
+ if (elanInterfaces.size() == 1) {//1st dpn interface
+ ElanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance);
+ }
+ 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) {
+ boolean isInterfaceOperational = isOperational(interfaceInfo);
+ 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 ( isInterfaceOperational ) {
+ // Setting SMAC, DMAC, UDMAC in this DPN and also in other DPNs
+ ElanUtils.setupMacFlows(elanInstance, interfaceInfo, ElanConstants.STATIC_MAC_TIMEOUT, physAddress.getValue());
+ }
+ }
+
+ if( isInterfaceOperational ) {
+ // Add MAC in TOR's remote MACs via OVSDB. Outside of the loop on purpose.
+ ElanL2GatewayUtils.scheduleAddDpnMacInExtDevices(elanInstance.getElanInstanceName(), dpId, staticMacAddresses);
+ }
+ }
+ }
+
+ 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
+ setupElanBroadcastGroups(elanInfo, interfaceInfo.getDpId());
+
+ setupLocalBroadcastGroups(elanInfo, interfaceInfo);
+ //Terminating Service , UnknownDMAC Table.
+ setupTerminateServiceTable(elanInfo, interfaceInfo);
+ ElanUtils.setupTermDmacFlows(interfaceInfo, mdsalManager);
+ 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
+ setElanBCGrouponOtherDpns(elanInfo, interfaceInfo);
+ }
+ }
+
+ public void setupFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
+ int ifTag = interfaceInfo.getInterfaceTag();
+ Flow flow = MDSALUtil.buildFlowNew(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)), getTunnelIdMatchForFilterEqualsLPortTag(ifTag), ElanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
+
+ mdsalManager.installFlow(interfaceInfo.getDpId(), flow);
+
+ Flow flowEntry = MDSALUtil.buildFlowNew(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),
+ MDSALUtil.buildInstructionsDrop());
+
+ mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntry);
+ }
+
+ public void removeFilterEqualsTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
+ int ifTag = interfaceInfo.getInterfaceTag();
+ Flow flow = MDSALUtil.buildFlowNew(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)), getTunnelIdMatchForFilterEqualsLPortTag(ifTag), ElanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
+
+ mdsalManager.removeFlow(interfaceInfo.getDpId(), flow);
+
+ Flow flowEntity = MDSALUtil.buildFlowNew(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),
+ MDSALUtil.buildInstructionsDrop());
+
+ mdsalManager.removeFlow(interfaceInfo.getDpId(), flowEntity);
+ }
+
+ private List<Bucket> getRemoteBCGroupBucketInfos(ElanInstance elanInfo,
+ int bucketKeyStart, InterfaceInfo interfaceInfo) {
+ BigInteger dpnId = interfaceInfo.getDpId();
+ int elanTag = elanInfo.getElanTag().intValue();
+ int bucketId = bucketKeyStart;
+ List<Bucket> listBuckets = new ArrayList<Bucket>();
+ 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 {
+ List<Action> listAction = ElanUtils.getInternalItmEgressAction(dpnId, dpnInterface.getDpId(), elanTag);
+ listBuckets.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
+ bucketId++;
+ } catch (Exception ex) {
+ logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnId, dpnInterface.getDpId() );
+ }
+ }
+ }
+ List<Bucket> elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId, bucketId);
+ listBuckets.addAll(elanL2GwDevicesBuckets);
+ }
+ return listBuckets;
+ }
+
+ private List<Bucket> getRemoteBCGroupBuckets(ElanInstance elanInfo, BigInteger dpnId, int bucketId) {
+ int elanTag = elanInfo.getElanTag().intValue();
+ List<Bucket> listBucketInfo = new ArrayList<Bucket>();
+ 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 {
+ List<Action> listActionInfo = ElanUtils.getInternalItmEgressAction(dpnId, dpnInterface.getDpId(), elanTag);
+ listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, 0, bucketId, 0xffffffffL, 0xffffffffL));
+ bucketId++;
+ } catch (Exception ex) {
+ logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnId, dpnInterface.getDpId() );
+ }
+ }
+ }
+
+ List<Bucket> elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId, bucketId);
+ listBucketInfo.addAll(elanL2GwDevicesBuckets);
+ }
+ return listBucketInfo;
+ }
+
+ private void setElanBCGrouponOtherDpns(ElanInstance elanInfo,
+ InterfaceInfo interfaceInfo) {
+ BigInteger dpnId = interfaceInfo.getDpId();
+ int elanTag = elanInfo.getElanTag().intValue();
+ long groupId = ElanUtils.getElanRemoteBCGID(elanTag);
+ List<Bucket> listBucket = new ArrayList<Bucket>();
+ int bucketId = 0;
+ ElanDpnInterfacesList elanDpns = ElanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
+ if(elanDpns != null) {
+ List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
+ for(DpnInterfaces dpnInterface : dpnInterfaceses) {
+ List<Bucket> remoteListBucketInfo = new ArrayList<Bucket>();
+ if(ElanUtils.isDpnPresent(dpnInterface.getDpId()) && !dpnInterface.getDpId().equals(dpnId) && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
+ for(String ifName : dpnInterface.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;
+ }
+
+ listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
+ bucketId++;
+ }
+ remoteListBucketInfo.addAll(listBucket);
+ for(DpnInterfaces otherFes : dpnInterfaceses) {
+ if (ElanUtils.isDpnPresent(otherFes.getDpId()) && otherFes.getDpId() != dpnInterface.getDpId()
+ && otherFes.getInterfaces() != null && ! otherFes.getInterfaces().isEmpty()) {
+ try {
+ List<Action> remoteListActionInfo = ElanUtils.getInternalItmEgressAction(dpnInterface.getDpId(), otherFes.getDpId(), elanTag);
+ remoteListBucketInfo.add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,MDSALUtil.WATCH_GROUP));
+ bucketId++;
+ } catch (Exception ex) {
+ logger.error( "Logical Group Interface not found between source Dpn - {}, destination Dpn - {} " ,dpnInterface.getDpId(), otherFes.getDpId() );
+ return;
+ }
+ }
+ }
+ List<Bucket> elanL2GwDevicesBuckets = getRemoteBCGroupBucketsOfElanL2GwDevices(elanInfo, dpnId,
+ bucketId);
+ remoteListBucketInfo.addAll(elanL2GwDevicesBuckets);
+
+ if (remoteListBucketInfo.size() == 0) {
+ logger.debug( "No ITM is present on Dpn - {} " ,dpnInterface.getDpId());
+ continue;
+ }
+ Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(remoteListBucketInfo));
+ mdsalManager.syncInstallGroup(dpnInterface.getDpId(), group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the bucket info with the given interface as the only bucket.
+ */
+ private Bucket getLocalBCGroupBucketInfo(InterfaceInfo interfaceInfo, int bucketIdStart) {
+ return MDSALUtil.buildBucket(getInterfacePortActions(interfaceInfo), MDSALUtil.GROUP_WEIGHT, bucketIdStart, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP);
+ }
+
+ 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<MatchInfo> buildMatchesForVni(Long vni) {
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ MatchInfo match = new MatchInfo(MatchFieldType.tunnel_id,
+ new BigInteger[]{BigInteger.valueOf(vni)} );
+ mkMatches.add(match);
+ return mkMatches;
+ }
+
+ private List<Instruction> getInstructionsForOutGroup(
+ long groupId) {
+ List<Instruction> mkInstructions = new ArrayList<Instruction>();
+ List <Action> actions = new ArrayList <Action> ();
+ actions.add(new ActionInfo(ActionType.group, new String[]{Long.toString(groupId)}).buildAction());
+ mkInstructions.add(MDSALUtil.getWriteActionsInstruction(actions, 0));
+ return mkInstructions;
+ }
+
+ private List<MatchInfo> getMatchesForElanTag(long elanTag, boolean isSHFlagSet) {
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ // Matching metadata
+ mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ ElanUtils.getElanMetadataLabel(elanTag, isSHFlagSet),
+ MetaDataUtil.METADATA_MASK_SERVICE_SH_FLAG}));
+ return mkMatches;
+ }
+
+
+
+
+ /**
+ * Builds the list of instructions to be installed in the External Tunnel table (38), which so far
+ * consists in writing the elanTag in metadata and send packet to the new DHCP table
+ *
+ * @param elanTag elanTag to be written in metadata when flow is selected
+ * @return the instructions ready to be installed in a flow
+ */
+ private List<InstructionInfo> getInstructionsExtTunnelTable(Long elanTag) {
+ List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
+ mkInstructions.add(new InstructionInfo(InstructionType.write_metadata,
+ new BigInteger[] {
+ ElanUtils.getElanMetadataLabel(elanTag),
+ ElanUtils.getElanMetadataMask()
+ } ) );
+ // TODO (eperefr) We should point to SMAC or DMAC depending on a configuration property to enable
+ // mac learning
+ mkInstructions.add(new InstructionInfo(InstructionType.goto_table,
+ new long[] { ElanConstants.ELAN_DMAC_TABLE }));
+
+ 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.installDmacFlowsToInternalRemoteMac(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 setupElanBroadcastGroups(ElanInstance elanInfo, BigInteger dpnId) {
+ List<Bucket> listBucket = new ArrayList<Bucket>();
+ int bucketId = 0;
+ long groupId = ElanUtils.getElanRemoteBCGID(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
+ // FIXME: interfaceType to be obtained dynamically. It doesn't
+ // affect the functionality here as it is nowhere used.
+ InterfaceType interfaceType = InterfaceInfo.InterfaceType.VLAN_INTERFACE;
+ InterfaceInfo ifInfo = interfaceManager.getInterfaceInfoFromOperationalDataStore(ifName, interfaceType);
+ if (!isOperational(ifInfo)) {
+ continue;
+ }
+
+ listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
+ bucketId++;
+ }
+ List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, dpnId, bucketId);
+ listBucket.addAll(listBucketInfoRemote);
+
+ Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBucket));
+ logger.trace("installing the remote BroadCast Group:{}", group);
+ mdsalManager.syncInstallGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
+ }
+
+ public void setupLocalBroadcastGroups(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
+ List<Bucket> listBucket = new ArrayList<Bucket>();
+ int bucketId = 0;
+ 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;
+ }
+
+ listBucket.add(MDSALUtil.buildBucket(getInterfacePortActions(ifInfo), MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
+ bucketId++;
+ }
+
+ Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBucket));
+ logger.trace("installing the localBroadCast Group:{}", group);
+ mdsalManager.syncInstallGroup(dpnId, group, ElanConstants.DELAY_TIME_IN_MILLISECOND);
+ }
+
+ public void removeLocalBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
+ BigInteger dpnId = interfaceInfo.getDpId();
+ long groupId = ElanUtils.getElanLocalBCGID(elanInfo.getElanTag());
+ List<Bucket> listBuckets = new ArrayList<>();
+ int bucketId = 0;
+ listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId));
+ //listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, 1, interfaceInfo));
+ Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBuckets));
+ logger.trace("deleted the localBroadCast Group:{}", group);
+ mdsalManager.syncRemoveGroup(dpnId, group);
+ }
+
+ public void removeElanBroadcastGroup(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
+ int bucketId = 0;
+ List<Bucket> listBuckets = new ArrayList<>();
+ listBuckets.add(getLocalBCGroupBucketInfo(interfaceInfo, bucketId));
+ bucketId++;
+ listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, bucketId, interfaceInfo));
+ BigInteger dpnId = interfaceInfo.getDpId();
+ long groupId = ElanUtils.getElanRemoteBCGID(elanInfo.getElanTag());
+ Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll, MDSALUtil.buildBucketLists(listBuckets));
+ logger.trace("deleting the remoteBroadCast group:{}", group);
+ mdsalManager.syncRemoveGroup(dpnId, group);
+ }
+
+ /**
+ * Installs a flow in the External Tunnel table consisting in translating
+ * the VNI retrieved from the packet that came over a tunnel with a TOR into
+ * elanTag that will be used later in the ELANs pipeline.
+ *
+ * @param dpnId
+ * the dpn id
+ * @param elanInfo
+ * the elan info
+ */
+ public void setExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo) {
+ long elanTag = elanInfo.getElanTag();
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId,
+ NwConstants.EXTERNAL_TUNNEL_TABLE,
+ getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanTag),
+ 5, // prio
+ elanInfo.getElanInstanceName(), // flowName
+ 0, // idleTimeout
+ 0, // hardTimeout
+ ITMConstants.COOKIE_ITM_EXTERNAL.add(BigInteger.valueOf(elanTag)),
+ buildMatchesForVni(elanInfo.getVni()),
+ getInstructionsExtTunnelTable(elanTag) );
+
+ mdsalManager.installFlow(flowEntity);
+ }
+
+ /**
+ * Removes, from External Tunnel table, the flow that translates from VNI to elanTag.
+ * Important: ensure this method is only called whenever there is no other ElanInterface in the specified DPN
+ *
+ * @param dpnId DPN whose Ext Tunnel table is going to be modified
+ * @param elanInfo holds the elanTag needed for selecting the flow to be removed
+ */
+ public void unsetExternalTunnelTable(BigInteger dpnId, ElanInstance elanInfo) {
+ // TODO (eperefr): Use DataStoreJobCoordinator in order to avoid that removing the last ElanInstance plus
+ // adding a new one does (almost at the same time) are executed in that exact order
+
+ String flowId = getFlowRef(NwConstants.EXTERNAL_TUNNEL_TABLE, elanInfo.getElanTag());
+ FlowEntity flowEntity = new FlowEntity(dpnId);
+ flowEntity.setTableId(NwConstants.EXTERNAL_TUNNEL_TABLE);
+ flowEntity.setFlowId(flowId);
+ mdsalManager.removeFlow(flowEntity);
+ }
+
+ public void setupTerminateServiceTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
+ long elanTag = elanInfo.getElanTag();
+ Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE, getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, elanTag),
+ 5, String.format("%s:%d","ITM Flow Entry ",elanTag), 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(elanTag)), ElanUtils.getTunnelMatchesForServiceId((int)elanTag),
+ getInstructionsForOutGroup(ElanUtils.getElanLocalBCGID(elanTag)));
+
+ mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntity);
+ }
+
+ public void setupUnknownDMacTable(ElanInstance elanInfo, InterfaceInfo interfaceInfo) {
+ long elanTag = elanInfo.getElanTag();
+ Flow flowEntity = MDSALUtil.buildFlowNew(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag, /*SH flag*/false),
+ 5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)), getMatchesForElanTag(elanTag, /*SH flag*/false),
+ getInstructionsForOutGroup(ElanUtils.getElanRemoteBCGID(elanTag)));
+
+ mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntity);
+
+ // only if vni is present in elanInfo, perform the following
+ if (elanInfo.getVni() != null && elanInfo.getVni() != 0) {
+ Flow flowEntity2 = MDSALUtil.buildFlowNew(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag, /*SH flag*/true),
+ 5, elanInfo.getElanInstanceName(), 0, 0, ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)), getMatchesForElanTag(elanTag, /*SH flag*/true),
+ getInstructionsForOutGroup(ElanUtils.getElanLocalBCGID(elanTag)));
+ mdsalManager.installFlow(interfaceInfo.getDpId(), flowEntity2);
+ }
+
+ }
+
+
+ private void removeStaticELanFlows(final ElanInstance elanInfo, final InterfaceInfo interfaceInfo) {
+ BigInteger dpId = interfaceInfo.getDpId();
+ /*
+ * If there are not elan ports, remove the unknown smac and default dmac
+ * flows
+ */
+ DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanInfo.getElanInstanceName(), dpId);
+ if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null || dpnInterfaces.getInterfaces().isEmpty()) {
+ // No more Elan Interfaces in this DPN
+ logger.debug("deleting the elan: {} present on dpId: {}", elanInfo.getElanInstanceName(), dpId);
+ removeDefaultTermFlow(dpId, elanInfo.getElanTag());
+ removeDefaultTermFlow(dpId, interfaceInfo.getInterfaceTag());
+ removeUnknownDmacFlow(dpId, elanInfo);
+ removeElanBroadcastGroup(elanInfo, interfaceInfo);
+ removeLocalBroadcastGroup(elanInfo, interfaceInfo);
+ if ( elanInfo.getVni() != null && elanInfo.getVni().longValue() != 0 ) {
+ unsetExternalTunnelTable(dpId, elanInfo);
+ }
+ removeFilterEqualsTable(elanInfo, interfaceInfo);
+ } else {
+ setupElanBroadcastGroups(elanInfo, dpId);
+ setupLocalBroadcastGroups(elanInfo, interfaceInfo);
+ removeFilterEqualsTable(elanInfo, interfaceInfo);
+ }
+ }
+
+ private void removeUnknownDmacFlow(BigInteger dpId, ElanInstance elanInfo) {
+// Flow flow = getUnknownDmacFlowEntity(dpId, elanInfo);
+// mdsalManager.removeFlow(dpId, flow);
+ Flow flow = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE,
+ elanInfo.getElanTag(), /*SH flag*/ false)))
+ .setTableId(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE)
+ .build();
+ mdsalManager.removeFlow(dpId, flow);
+
+ if ( elanInfo.getVni() != null && elanInfo.getVni() > 0 ) {
+ Flow flow2 = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE,
+ elanInfo.getElanTag(), /*SH flag*/ true)))
+ .setTableId(ElanConstants.ELAN_UNKNOWN_DMAC_TABLE)
+ .build();
+ mdsalManager.removeFlow(dpId, flow2);
+ }
+
+
+ }
+
+ private void removeDefaultTermFlow(BigInteger dpId, long elanTag) {
+ ElanUtils.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 String getFlowRef(long tableId, long elanTag) {
+ return new StringBuffer().append(tableId).append(elanTag).toString();
+ }
+
+ private String getUnknownDmacFlowRef(long tableId, long elanTag, boolean shFlag) {
+ return new StringBuffer().append(tableId).append(elanTag).append(shFlag).toString();
+ }
+
+ private List<Action> getInterfacePortActions(InterfaceInfo interfaceInfo) {
+ List<Action> listAction = new ArrayList<Action>();
+ int actionKey = 0;
+ listAction.add((new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {BigInteger.valueOf(interfaceInfo.getInterfaceTag())}, actionKey)).buildAction());
+ actionKey++;
+ listAction.add((new ActionInfo(ActionType.nx_resubmit,
+ new String[] {String.valueOf(ElanConstants.ELAN_FILTER_EQUALS_TABLE)}, actionKey)).buildAction());
+ return listAction;
+ }
+
+ private void updateElanDpnInterfacesList(String elanInstanceName, BigInteger dpId, List<String> interfaceNames) {
+ DpnInterfaces dpnInterface = new DpnInterfacesBuilder().setDpId(dpId)
+ .setInterfaces(interfaceNames).setKey(new DpnInterfacesKey(dpId)).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, ElanUtils.getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId),
+ dpnInterface);
+ }
+
+ /**
+ * Delete elan dpn interface from operational DS.
+ *
+ * @param elanInstanceName
+ * the elan instance name
+ * @param dpId
+ * the dp id
+ */
+ private void deleteElanDpnInterface(String elanInstanceName, BigInteger dpId) {
+ 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) {
+ if (interfaceInfo == null) {
+ return false;
+ }
+ return 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 handleInternalTunnelStateEvent(BigInteger srcDpId, BigInteger dstDpId) {
+ ElanDpnInterfaces dpnInterfaceLists = ElanUtils.getElanDpnInterfacesList();
+ 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);
+ ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanName);
+ // update Remote BC Group
+ setupElanBroadcastGroups(elanInfo, srcDpId);
+
+ DpnInterfaces dpnInterface = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, srcDpId);
+ Set<String> interfaceLists = new HashSet<>();
+ interfaceLists.addAll(dpnInterface.getInterfaces());
+ for(String ifName : interfaceLists) {
+ InterfaceInfo interfaceInfo = interfaceManager.getInterfaceInfo(ifName);
+ if (isOperational(interfaceInfo)) {
+ elanInterfaceManager.installDMacAddressTables(elanInfo, interfaceInfo, dstDpId);
+ }
+ }
+ }
+
+ }
+ }
+
+ /**
+ * Handle external tunnel state event.
+ *
+ * @param externalTunnel
+ * the external tunnel
+ * @param intrf
+ * the interface
+ */
+ public void handleExternalTunnelStateEvent(ExternalTunnel externalTunnel, Interface intrf) {
+ if (!validateExternalTunnelStateEvent(externalTunnel, intrf)) {
+ return;
+ }
+ // dpId/externalNodeId will be available either in source or destination
+ // based on the tunnel end point
+ BigInteger dpId = null;
+ NodeId externalNodeId = null;
+ if (StringUtils.isNumeric(externalTunnel.getSourceDevice())) {
+ dpId = new BigInteger(externalTunnel.getSourceDevice());
+ externalNodeId = new NodeId(externalTunnel.getDestinationDevice());
+ } else if (StringUtils.isNumeric(externalTunnel.getDestinationDevice())) {
+ dpId = new BigInteger(externalTunnel.getDestinationDevice());
+ externalNodeId = new NodeId(externalTunnel.getSourceDevice());
+ }
+ if (dpId == null || externalNodeId == null) {
+ logger.error("Dp ID / externalNodeId not found in external tunnel {}", externalTunnel);
+ return;
+ }
+
+ ElanDpnInterfaces dpnInterfaceLists = ElanUtils.getElanDpnInterfacesList();
+ if (dpnInterfaceLists == null) {
+ return;
+ }
+ List<ElanDpnInterfacesList> elanDpnIf = dpnInterfaceLists.getElanDpnInterfacesList();
+ for (ElanDpnInterfacesList elanDpns : elanDpnIf) {
+ String elanName = elanDpns.getElanInstanceName();
+ ElanInstance elanInfo = ElanUtils.getElanInstanceByName(elanName);
+
+ DpnInterfaces dpnInterfaces = ElanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
+ if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null
+ || dpnInterfaces.getInterfaces().isEmpty()) {
+ continue;
+ }
+ logger.debug("Elan instance:{} is present in Dpn:{} ", elanName, dpId);
+
+ setupElanBroadcastGroups(elanInfo, dpId);
+ // install L2gwDevices local macs in dpn.
+ ElanL2GatewayUtils.installL2gwDeviceMacsInDpn(dpId, externalNodeId, elanInfo);
+ // Install dpn macs on external device
+ ElanL2GatewayUtils.installDpnMacsInL2gwDevice(elanName, new HashSet<>(dpnInterfaces.getInterfaces()), dpId,
+ externalNodeId);
+ }
+ logger.info("Handled ExternalTunnelStateEvent for {}", externalTunnel);
+ }
+
+ /**
+ * Validate external tunnel state event.
+ *
+ * @param externalTunnel
+ * the external tunnel
+ * @param intrf
+ * the intrf
+ * @return true, if successful
+ */
+ private boolean validateExternalTunnelStateEvent(ExternalTunnel externalTunnel, Interface intrf) {
+ if (intrf.getOperStatus() == Interface.OperStatus.Up) {
+ String srcDevice = externalTunnel.getDestinationDevice();
+ String destDevice = externalTunnel.getSourceDevice();
+ ExternalTunnel otherEndPointExtTunnel = ElanUtils.getExternalTunnel(srcDevice, destDevice,
+ LogicalDatastoreType.CONFIGURATION);
+ if (logger.isTraceEnabled()) {
+ logger.trace("Validating external tunnel state: src tunnel {}, dest tunnel {}", externalTunnel,
+ otherEndPointExtTunnel);
+ }
+ if (otherEndPointExtTunnel != null) {
+ boolean otherEndPointInterfaceOperational = ElanUtils
+ .isInterfaceOperational(otherEndPointExtTunnel.getTunnelInterfaceName(), broker);
+ if (otherEndPointInterfaceOperational) {
+ return true;
+ } else {
+ logger.debug("Other end [{}] of the external tunnel is not yet UP for {}",
+ otherEndPointExtTunnel.getTunnelInterfaceName(), externalTunnel);
+ }
+ }
+ }
+ return false;
+ }
+
+ public void handleInterfaceUpdated(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);
+
+ if (elanInstance.getVni() != null && elanInstance.getVni() != 0) {
+ List<PhysAddress> macAddresses = ElanUtils
+ .getElanInterfaceMacAddresses(interfaceInfo.getInterfaceName());
+ if (macAddresses != null && !macAddresses.isEmpty()) {
+ ElanL2GatewayUtils.scheduleAddDpnMacInExtDevices(elanInstance.getElanInstanceName(),
+ dpId, macAddresses);
+ }
+ }
+ } 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);
+
+ // Removing MACs from External Devices belonging to this ELAN
+ if (elanInstance.getVni() != null && elanInstance.getVni() != 0) {
+ List<PhysAddress> macAddresses = ElanUtils
+ .getElanInterfaceMacAddresses(interfaceInfo.getInterfaceName());
+ if (macAddresses != null && !macAddresses.isEmpty()) {
+ ElanL2GatewayUtils.removeMacsFromElanExternalDevices(elanInstance, macAddresses);
+ }
+ }
+ }
+ }
+
+ private List<MatchInfo> getMatchesForFilterEqualsLPortTag(int LportTag) {
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ // Matching metadata
+ mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ MetaDataUtil.getLportTagMetaData(LportTag),
+ MetaDataUtil.METADATA_MASK_LPORT_TAG }));
+ mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(LportTag)}));
+ return mkMatches;
+ }
+
+
+ private List<MatchInfo> getTunnelIdMatchForFilterEqualsLPortTag(int LportTag) {
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ // Matching metadata
+ mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {
+ BigInteger.valueOf(LportTag)}));
+ return mkMatches;
+ }
+
+ public void updateRemoteBroadcastGroupForAllElanDpns(ElanInstance elanInfo) {
+ List<DpnInterfaces> dpns = ElanUtils.getInvolvedDpnsInElan(elanInfo.getElanInstanceName());
+ if (dpns == null) {
+ return;
+ }
+ for (DpnInterfaces dpn : dpns) {
+ setupElanBroadcastGroups(elanInfo, dpn.getDpId());
+ }
+ }
+
+ public static List<Bucket> getRemoteBCGroupBucketsOfElanL2GwDevices(ElanInstance elanInfo, BigInteger dpnId,
+ int bucketId) {
+ List<Bucket> listBucketInfo = new ArrayList<Bucket>();
+ ConcurrentMap<String, L2GatewayDevice> map = ElanL2GwCacheUtils
+ .getInvolvedL2GwDevices(elanInfo.getElanInstanceName());
+ for (L2GatewayDevice device : map.values()) {
+ String interfaceName = ElanL2GatewayUtils.getExternalTunnelInterfaceName(String.valueOf(dpnId),
+ device.getHwvtepNodeId());
+ if (interfaceName == null) {
+ continue;
+ }
+ List<Action> listActionInfo = ElanUtils.buildItmEgressActions(interfaceName, elanInfo.getVni());
+ listBucketInfo.add(MDSALUtil.buildBucket(listActionInfo, MDSALUtil.GROUP_WEIGHT, bucketId,
+ MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
+ bucketId++;
+ }
+ return listBucketInfo;
+ }
+
+}
+
+
--- /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 java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class ElanInterfaceRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
+ private String key;
+ private ElanInstance elanInfo;
+ private String interfaceName;
+ private InterfaceInfo interfaceInfo;
+ private ElanInterfaceManager dataChangeListener;
+
+ public ElanInterfaceRemoveWorker(String key, ElanInstance elanInfo, String interfaceName,
+ InterfaceInfo interfaceInfo, ElanInterfaceManager dataChangeListener) {
+ super();
+ this.key = key;
+ this.elanInfo = elanInfo;
+ this.interfaceName = interfaceName;
+ this.interfaceInfo = interfaceInfo;
+ this.dataChangeListener = dataChangeListener;
+ }
+
+ @Override
+ public String toString() {
+ return "ElanInterfaceRemoveWorker [key=" + key + ", elanInfo=" + elanInfo +
+ ", interfaceName=" + interfaceName
+ + ", interfaceInfo=" + interfaceInfo + "]";
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ dataChangeListener.removeElanInterface(elanInfo, interfaceName, interfaceInfo);
+ return futures;
+ }
+
+}
--- /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 java.math.BigInteger;
+import java.util.List;
+
+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.datastoreutils.DataStoreJobCoordinator;
+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.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+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.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+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.itm.op.rev150701.TunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ElanInterfaceStateChangeListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
+ private DataBroker broker;
+ private IInterfaceManager interfaceManager;
+ private ElanInterfaceManager elanInterfaceManager;
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private static final Logger logger = LoggerFactory.getLogger(ElanInterfaceStateChangeListener.class);
+
+ public ElanInterfaceStateChangeListener(final DataBroker db, final ElanInterfaceManager ifManager) {
+ super(Interface.class);
+ broker = db;
+ elanInterfaceManager = ifManager;
+ registerListener(db);
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = broker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), ElanInterfaceStateChangeListener.this, AsyncDataBroker.DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ logger.error("Elan Interfaces DataChange listener registration fail!", e);
+ throw new IllegalStateException("ElanInterface registration Listener failed.", e);
+ }
+ }
+
+ private InstanceIdentifier<Interface> getWildCardPath() {
+ return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
+ }
+
+ public void setInterfaceManager(IInterfaceManager interfaceManager) {
+ this.interfaceManager = interfaceManager;
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Interface> identifier, Interface delIf) {
+ logger.trace("Received interface {} Down event", delIf);
+ String interfaceName = delIf.getName();
+ ElanInterface elanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName);
+ if(elanInterface == null) {
+ logger.debug("No Elan Interface is created for the interface:{} ", interfaceName);
+ return;
+ }
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(delIf.getLowerLayerIf().get(0));
+ BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
+ InterfaceInfo interfaceInfo = new InterfaceInfo(dpId, nodeConnectorId.getValue());
+ interfaceInfo.setInterfaceName(interfaceName);
+ interfaceInfo.setInterfaceType(InterfaceInfo.InterfaceType.VLAN_INTERFACE);
+ interfaceInfo.setInterfaceTag(delIf.getIfIndex());
+ String elanInstanceName = elanInterface.getElanInstanceName();
+ ElanInstance elanInstance = ElanUtils.getElanInstanceByName(elanInstanceName);
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ ElanInterfaceRemoveWorker removeWorker = new ElanInterfaceRemoveWorker(elanInstanceName, elanInstance,
+ interfaceName, interfaceInfo, elanInterfaceManager);
+ coordinator.enqueueJob(elanInstanceName, removeWorker, ElanConstants.JOB_MAX_RETRIES);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Interface> identifier, Interface original, Interface update) {
+ logger.trace("Operation Interface update event - Old: {}, New: {}", original, update);
+ String interfaceName = update.getName();
+ if (update.getType() == null) {
+ logger.trace("Interface type for interface {} is null", interfaceName);
+ return;
+ }
+ if(update.getType().equals(Tunnel.class)) {
+ if (update.getOperStatus().equals(Interface.OperStatus.Up)) {
+ InternalTunnel internalTunnel = getTunnelState(interfaceName);
+ if (internalTunnel != null) {
+ elanInterfaceManager.handleInternalTunnelStateEvent(internalTunnel.getSourceDPN(), internalTunnel.getDestinationDPN());
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
+ logger.trace("Received interface {} up event", intrf);
+ String interfaceName = intrf.getName();
+ ElanInterface elanInterface = ElanUtils.getElanInterfaceByElanInterfaceName(interfaceName);
+ if(elanInterface == null) {
+ if (intrf.getType() != null && intrf.getType().equals(Tunnel.class)) {
+ if(intrf.getOperStatus().equals(Interface.OperStatus.Up)) {
+ InternalTunnel internalTunnel = getTunnelState(interfaceName);
+ if (internalTunnel != null) {
+ elanInterfaceManager.handleInternalTunnelStateEvent(internalTunnel.getSourceDPN(),
+ internalTunnel.getDestinationDPN());
+ }
+ }
+ }
+ return;
+ }
+ InstanceIdentifier<ElanInterface> elanInterfaceId = ElanUtils.getElanInterfaceConfigurationDataPathId(interfaceName);
+ elanInterfaceManager.add(elanInterfaceId, elanInterface);
+ }
+
+ @Override
+ public void close() throws Exception {
+
+ }
+
+ public InternalTunnel getTunnelState(String interfaceName) {
+ InternalTunnel internalTunnel = null;
+ TunnelList tunnelList = ElanUtils.buildInternalTunnel(broker);
+ if (tunnelList != null && tunnelList.getInternalTunnel() != null) {
+ List<InternalTunnel> internalTunnels = tunnelList.getInternalTunnel();
+ for (InternalTunnel tunnel : internalTunnels) {
+ if (tunnel.getTunnelInterfaceName().equalsIgnoreCase(interfaceName)) {
+ internalTunnel = tunnel;
+ break;
+ }
+ }
+ }
+ return internalTunnel;
+ }
+}
--- /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.ClusteredDataChangeListener;
+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.datastoreutils.AsyncClusteredDataChangeListenerBase;
+import org.opendaylight.vpnservice.elan.utils.ElanClusterUtils;
+import org.opendaylight.vpnservice.elan.utils.ElanUtils;
+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.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ElanInterfaceStateClusteredListener extends
+ AsyncClusteredDataChangeListenerBase<Interface, ElanInterfaceStateClusteredListener> implements AutoCloseable {
+ private DataBroker broker;
+ private ElanInterfaceManager elanInterfaceManager;
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+
+ private static final Logger logger = LoggerFactory.getLogger(ElanInterfaceStateClusteredListener.class);
+
+ public ElanInterfaceStateClusteredListener(final DataBroker db, final ElanInterfaceManager ifManager) {
+ super(Interface.class, ElanInterfaceStateClusteredListener.class);
+ broker = db;
+ elanInterfaceManager = ifManager;
+ registerListener(db);
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = broker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), ElanInterfaceStateClusteredListener.this, AsyncDataBroker.DataChangeScope.BASE);
+ } catch (final Exception e) {
+ logger.error("Elan Interfaces DataChange listener registration fail!", e);
+ throw new IllegalStateException("ElanInterface registration Listener failed.", e);
+ }
+ }
+
+ @Override
+ public InstanceIdentifier<Interface> getWildCardPath() {
+ return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
+ }
+
+ @Override
+ protected ClusteredDataChangeListener getDataChangeListener() {
+ return ElanInterfaceStateClusteredListener.this;
+ }
+
+ @Override
+ protected AsyncDataBroker.DataChangeScope getDataChangeScope() {
+ return AsyncDataBroker.DataChangeScope.BASE;
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Interface> identifier, Interface delIf) {
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Interface> identifier, Interface original, final Interface update) {
+ add(identifier, update);
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Interface> identifier, final Interface intrf) {
+ if (intrf.getType() != null && intrf.getType().equals(Tunnel.class)) {
+ if (intrf.getOperStatus().equals(Interface.OperStatus.Up)) {
+ final String interfaceName = intrf.getName();
+
+ ElanClusterUtils.runOnlyInLeaderNode(new Runnable() {
+ @Override
+ public void run() {
+ logger.debug("running external tunnel update job for interface {} added", interfaceName);
+ handleExternalTunnelUpdate(interfaceName, intrf);
+ }
+ });
+ }
+ }
+ }
+
+ private void handleExternalTunnelUpdate(String interfaceName, Interface update) {
+ ExternalTunnel externalTunnel = ElanUtils.getExternalTunnel(interfaceName, LogicalDatastoreType.CONFIGURATION);
+ if (externalTunnel != null) {
+ logger.debug("handling external tunnel update event for ext device dst {} src {} ",
+ externalTunnel.getDestinationDevice(), externalTunnel.getSourceDevice());
+ elanInterfaceManager.handleExternalTunnelStateEvent(externalTunnel, update);
+ } else {
+ logger.trace("External tunnel not found with interfaceName: {}", interfaceName);
+ }
+ }
+}
--- /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(":");
+ if(node.length < 2) {
+ logger.warn("Unexpected nodeId {}", nodeId.getValue());
+ return;
+ }
+ 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 java.math.BigInteger;
+
+import org.opendaylight.controller.liblldp.NetUtils;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.elan.l2gw.utils.ElanL2GatewayUtils;
+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.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
+import org.opendaylight.vpnservice.mdsalutil.NWUtil;
+import org.opendaylight.vpnservice.mdsalutil.packet.Ethernet;
+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.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 com.google.common.base.Optional;
+
+import java.util.Arrays;
+
+@SuppressWarnings("deprecation")
+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();
+
+ Optional<IfIndexInterface> interfaceInfoOp = ElanUtils.getInterfaceInfoByInterfaceTag(portTag);
+ if (!interfaceInfoOp.isPresent()) {
+ logger.warn("There is no interface for given portTag {}", portTag);
+ return;
+ }
+ String interfaceName = interfaceInfoOp.get().getInterfaceName();
+ ElanTagName elanTagName = ElanUtils.getElanInfoByElanTag(elanTag);
+ if (elanTagName == null) {
+ logger.warn("not able to find elanTagName in elan-tag-name-map for elan tag {}", elanTag);
+ return;
+ }
+ String elanName = elanTagName.getName();
+ 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);
+
+ BigInteger dpId = interfaceManager.getDpnForInterface(interfaceName);
+ ElanL2GatewayUtils.scheduleAddDpnMacInExtDevices(elanInstance.getElanInstanceName(), dpId,
+ Arrays.asList(physAddress));
+ } 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);
+ ElanL2GatewayUtils.removeMacsFromElanExternalDevices(elanInfo, Arrays.asList(macEntry.getMacAddress()));
+ }
+
+}
--- /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 java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.Future;
+
+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.clustering.EntityOwnershipService;
+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.elanmanager.exceptions.MacNotFoundException;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.elan.l2gw.internal.ElanL2GatewayProvider;
+import org.opendaylight.vpnservice.elan.statisitcs.ElanStatisticsImpl;
+import org.opendaylight.vpnservice.elan.statusanddiag.ElanStatusMonitor;
+import org.opendaylight.vpnservice.elan.utils.ElanClusterUtils;
+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.vpnservice.utils.hwvtep.HwvtepSouthboundUtils;
+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.yang.types.rev130715.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.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
+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.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+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 ElanInterfaceStateChangeListener elanInterfaceStateChangeListener;
+ private ElanInterfaceStateClusteredListener infStateChangeClusteredListener;
+ private ElanDpnInterfaceClusteredListener elanDpnInterfaceClusteredListener;
+ private ElanNodeListener elanNodeListener;
+ private NotificationService notificationService;
+ private RpcProviderRegistry rpcProviderRegistry;
+ private IITMProvider itmManager;
+ private ItmRpcService itmRpcService;
+ private DataBroker broker;
+ private ElanL2GatewayProvider elanL2GatewayProvider;
+
+ private EntityOwnershipService entityOwnershipService;
+
+ private static final ElanStatusMonitor elanStatusMonitor = ElanStatusMonitor.getInstance();
+ static DataStoreJobCoordinator dataStoreJobCoordinator;
+
+ public static void setDataStoreJobCoordinator(DataStoreJobCoordinator ds) {
+ dataStoreJobCoordinator = ds;
+ }
+
+ public static DataStoreJobCoordinator getDataStoreJobCoordinator() {
+ if (dataStoreJobCoordinator == null) {
+ dataStoreJobCoordinator = DataStoreJobCoordinator.getInstance();
+ }
+ return dataStoreJobCoordinator;
+ }
+
+
+ public ElanServiceProvider(RpcProviderRegistry rpcRegistry) {
+ rpcProviderRegistry = rpcRegistry;
+ elanStatusMonitor.registerMbean();
+ }
+
+ // private ElanInterfaceStateChangeListener elanInterfaceEventListener;
+ private ElanItmEventListener elanItmEventListener;
+
+ private static final Logger logger = LoggerFactory.getLogger(ElanServiceProvider.class);
+
+ @Override
+ public void onSessionInitiated(ProviderContext session) {
+ elanStatusMonitor.reportStatus("STARTING");
+ try {
+ createIdPool();
+ getDataStoreJobCoordinator();
+ broker = session.getSALService(DataBroker.class);
+
+ ElanUtils.setDataBroker(broker);
+ ElanUtils.setIfaceMgrRpcService(interfaceManagerRpcService);
+ ElanUtils.setItmRpcService(itmRpcService);
+ ElanUtils.setMdsalManager(mdsalManager);
+
+ elanForwardingEntriesHandler = new ElanForwardingEntriesHandler(broker);
+
+ elanInterfaceManager = ElanInterfaceManager.getElanInterfaceManager();
+ elanInterfaceManager.setInterfaceManager(interfaceManager);
+ elanInterfaceManager.setIdManager(idManager);
+ elanInterfaceManager.setMdSalApiManager(mdsalManager);
+ elanInterfaceManager.setDataBroker(broker);
+ elanInterfaceManager.setInterfaceManagerRpcService(interfaceManagerRpcService);
+ elanInterfaceManager.setElanForwardingEntriesHandler(elanForwardingEntriesHandler);
+
+ elanInstanceManager = ElanInstanceManager.getElanInstanceManager();
+ elanInstanceManager.setDataBroker(broker);
+ elanInstanceManager.setIdManager(idManager);
+ elanInstanceManager.setElanInterfaceManager(elanInterfaceManager);
+ elanInstanceManager.setInterfaceManager(interfaceManager);
+
+
+ elanNodeListener = new ElanNodeListener(broker, mdsalManager);
+
+ elanPacketInHandler = new ElanPacketInHandler(broker);
+ elanPacketInHandler.setInterfaceManager(interfaceManager);
+
+
+ elanSmacFlowEventListener = new ElanSmacFlowEventListener(broker);
+ elanSmacFlowEventListener.setMdSalApiManager(mdsalManager);
+ elanSmacFlowEventListener.setInterfaceManager(interfaceManager);
+ elanSmacFlowEventListener.setSalFlowService(session.getRpcService(SalFlowService.class));
+
+
+ // Initialize statistics rpc provider for elan
+ ElanStatisticsService interfaceStatsService = new ElanStatisticsImpl(broker, interfaceManager,
+ mdsalManager);
+ rpcProviderRegistry.addRpcImplementation(ElanStatisticsService.class, interfaceStatsService);
+
+ elanInterfaceStateChangeListener = new ElanInterfaceStateChangeListener(broker, elanInterfaceManager);
+ elanInterfaceStateChangeListener.setInterfaceManager(interfaceManager);
+
+ infStateChangeClusteredListener = new ElanInterfaceStateClusteredListener(broker, elanInterfaceManager);
+
+ elanDpnInterfaceClusteredListener = new ElanDpnInterfaceClusteredListener(broker, elanInterfaceManager);
+ ElanClusterUtils.setEntityOwnershipService(entityOwnershipService);
+ ElanClusterUtils.setDataStoreJobCoordinator(dataStoreJobCoordinator);
+ this.elanL2GatewayProvider = new ElanL2GatewayProvider(this);
+
+ elanInterfaceManager.registerListener();
+ elanInstanceManager.registerListener();
+ notificationService.registerNotificationListener(elanSmacFlowEventListener);
+ notificationService.registerNotificationListener(elanPacketInHandler);
+
+ elanStatusMonitor.reportStatus("OPERATIONAL");
+ } catch (Exception e) {
+ logger.error("Error initializing services", e);
+ elanStatusMonitor.reportStatus("ERROR");
+ }
+ }
+
+ 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 void setEntityOwnershipService(EntityOwnershipService entityOwnershipService) {
+ this.entityOwnershipService = entityOwnershipService;
+ }
+
+ public IInterfaceManager getInterfaceManager() {
+ return this.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;
+ }
+
+ public void setItmRpcService(ItmRpcService itmRpcService) {
+ this.itmRpcService = itmRpcService;
+ }
+
+ public ItmRpcService getItmRpcService() {
+ return itmRpcService;
+ }
+
+ public ElanInstanceManager getElanInstanceManager() {
+ return elanInstanceManager;
+ }
+
+ public ElanInterfaceManager getElanInterfaceManager() {
+ return elanInterfaceManager;
+ }
+
+ public EntityOwnershipService getEntityOwnershipService() {
+ return entityOwnershipService;
+ }
+
+ 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.getElanInstanceConfigurationDataPath(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.getElanInstanceConfigurationDataPath(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 {
+ this.elanInstanceManager.close();
+ this.elanL2GatewayProvider.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 java.math.BigInteger;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+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.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.FlowAdded;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeExperimenterErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved;
+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.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+@SuppressWarnings("deprecation")
+public class ElanSmacFlowEventListener implements SalFlowListener {
+ private final DataBroker broker;
+ private IInterfaceManager interfaceManager;
+ 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 setMdSalApiManager(IMdsalApiManager 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;
+ }
+ final 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;
+ }
+ Optional<IfIndexInterface> existingInterfaceInfo = ElanUtils.getInterfaceInfoByInterfaceTag(portTag);
+ if (!existingInterfaceInfo.isPresent()) {
+ logger.debug("Interface is not available for port Tag {}", portTag);
+ return;
+ }
+ String interfaceName = existingInterfaceInfo.get().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> macEntryIdForElanInterface = ElanUtils.getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress);
+ InstanceIdentifier<MacEntry> macEntryIdForElanInstance = ElanUtils.getMacEntryOperationalDataPath(elanTagInfo.getName(), physAddress);
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.delete(LogicalDatastoreType.OPERATIONAL, macEntryIdForElanInterface);
+ tx.delete(LogicalDatastoreType.OPERATIONAL, macEntryIdForElanInstance);
+ ListenableFuture<Void> writeResult = tx.submit();
+
+ //WRITE Callback
+ Futures.addCallback(writeResult, new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(Void noarg) {
+ logger.debug("Successfully removed macEntry {} from Operational Datastore", srcMacAddress);
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ logger.debug("Error {} while removing macEntry {} from Operational Datastore", error, srcMacAddress);
+ }
+ });
+ }
+ }
+}
--- /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.l2gw.internal;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.elanmanager.utils.ElanL2GwCacheUtils;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.elan.internal.ElanInstanceManager;
+import org.opendaylight.vpnservice.elan.internal.ElanInterfaceManager;
+import org.opendaylight.vpnservice.elan.internal.ElanServiceProvider;
+import org.opendaylight.vpnservice.elan.l2gw.listeners.HwvtepLocalUcastMacListener;
+import org.opendaylight.vpnservice.elan.l2gw.listeners.HwvtepLogicalSwitchListener;
+import org.opendaylight.vpnservice.elan.l2gw.listeners.HwvtepNodeListener;
+import org.opendaylight.vpnservice.elan.l2gw.listeners.HwvtepPhysicalLocatorListener;
+import org.opendaylight.vpnservice.elan.l2gw.listeners.HwvtepRemoteMcastMacListener;
+import org.opendaylight.vpnservice.elan.l2gw.listeners.L2GatewayConnectionListener;
+import org.opendaylight.vpnservice.elan.l2gw.utils.ElanL2GatewayMulticastUtils;
+import org.opendaylight.vpnservice.elan.l2gw.utils.ElanL2GatewayUtils;
+import org.opendaylight.vpnservice.elan.l2gw.utils.L2GatewayConnectionUtils;
+import org.opendaylight.vpnservice.utils.clustering.EntityOwnerUtils;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepSouthboundConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Elan L2 Gateway provider class.
+ */
+public class ElanL2GatewayProvider implements AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ElanL2GatewayProvider.class);
+
+ private DataBroker broker;
+ private EntityOwnershipService entityOwnershipService;
+ private ItmRpcService itmRpcService;
+ private ElanInstanceManager elanInstanceManager;
+ private ElanInterfaceManager elanInterfaceManager;
+
+ private L2GatewayConnectionListener l2GwConnListener;
+ private HwvtepNodeListener hwvtepNodeListener;
+ private HwvtepLocalUcastMacListener torMacsListener;
+ private HwvtepPhysicalLocatorListener physicalLocatorListener;
+
+ static DataStoreJobCoordinator dataStoreJobCoordinator;
+
+ /**
+ * Instantiates a new elan l2 gateway provider.
+ *
+ * @param elanServiceProvider
+ * the elan service provider
+ */
+ public ElanL2GatewayProvider(ElanServiceProvider elanServiceProvider) {
+ this.broker = elanServiceProvider.getBroker();
+ this.entityOwnershipService = elanServiceProvider.getEntityOwnershipService();
+ this.itmRpcService = elanServiceProvider.getItmRpcService();
+ this.elanInstanceManager = elanServiceProvider.getElanInstanceManager();
+ this.elanInterfaceManager = elanServiceProvider.getElanInterfaceManager();
+ dataStoreJobCoordinator = elanServiceProvider.getDataStoreJobCoordinator();
+ init();
+
+ LOG.info("ElanL2GatewayProvider Initialized");
+ }
+
+ /**
+ * Initialize Elan L2 Gateway.
+ */
+ private void init() {
+ ElanL2GwCacheUtils.createElanL2GwDeviceCache();
+ ElanL2GatewayUtils.setDataBroker(broker);
+ ElanL2GatewayUtils.setItmRpcService(itmRpcService);
+ ElanL2GatewayUtils.setDataStoreJobCoordinator(dataStoreJobCoordinator);
+
+ ElanL2GatewayMulticastUtils.setBroker(broker);
+ ElanL2GatewayMulticastUtils.setElanInstanceManager(elanInstanceManager);
+ ElanL2GatewayMulticastUtils.setElanInterfaceManager(elanInterfaceManager);
+ ElanL2GatewayMulticastUtils.setDataStoreJobCoordinator(dataStoreJobCoordinator);
+
+ L2GatewayConnectionUtils.setElanInstanceManager(elanInstanceManager);
+ L2GatewayConnectionUtils.setBroker(broker);
+ L2GatewayConnectionUtils.setDataStoreJobCoordinator(dataStoreJobCoordinator);
+
+ HwvtepRemoteMcastMacListener.setDataStoreJobCoordinator(dataStoreJobCoordinator);
+ HwvtepLogicalSwitchListener.setDataStoreJobCoordinator(dataStoreJobCoordinator);
+
+ this.torMacsListener = new HwvtepLocalUcastMacListener(broker);
+ this.l2GwConnListener = new L2GatewayConnectionListener(broker, elanInstanceManager);
+ this.hwvtepNodeListener = new HwvtepNodeListener(broker, elanInstanceManager, itmRpcService);
+ this.hwvtepNodeListener.registerListener(LogicalDatastoreType.OPERATIONAL, broker);
+
+ physicalLocatorListener = new HwvtepPhysicalLocatorListener(broker);
+ try {
+ EntityOwnerUtils.registerEntityCandidateForOwnerShip(entityOwnershipService,
+ HwvtepSouthboundConstants.ELAN_ENTITY_TYPE, HwvtepSouthboundConstants.ELAN_ENTITY_TYPE,
+ null/*listener*/);
+ } catch (CandidateAlreadyRegisteredException e) {
+ LOG.error("failed to register the entity");
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.AutoCloseable#close()
+ */
+ @Override
+ public void close() throws Exception {
+ this.torMacsListener.close();
+ this.l2GwConnListener.close();
+ this.hwvtepNodeListener.close();
+ LOG.info("ElanL2GatewayProvider Closed");
+ }
+}
--- /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.l2gw.jobs;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.vpnservice.elan.l2gw.utils.ElanL2GatewayUtils;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepSouthboundUtils;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.Devices;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+* Created by ekvsver on 4/15/2016.
+*/
+public class AssociateHwvtepToElanJob implements Callable<List<ListenableFuture<Void>>> {
+ DataBroker broker;
+ L2GatewayDevice l2GatewayDevice;
+ ElanInstance elanInstance;
+ Devices l2Device;
+ Integer defaultVlan;
+ boolean createLogicalSwitch;
+ private static final Logger LOG = LoggerFactory.getLogger(AssociateHwvtepToElanJob.class);
+
+ public AssociateHwvtepToElanJob(DataBroker broker, L2GatewayDevice l2GatewayDevice, ElanInstance elanInstance,
+ Devices l2Device, Integer defaultVlan, boolean createLogicalSwitch) {
+ this.broker = broker;
+ this.l2GatewayDevice = l2GatewayDevice;
+ this.elanInstance = elanInstance;
+ this.l2Device = l2Device;
+ this.defaultVlan = defaultVlan;
+ this.createLogicalSwitch = createLogicalSwitch;
+ LOG.debug("created assosiate l2gw connection job for {} {} ", elanInstance.getElanInstanceName(),
+ l2GatewayDevice.getHwvtepNodeId());
+ }
+
+ public String getJobKey() {
+ return elanInstance.getElanInstanceName();
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ String hwvtepNodeId = l2GatewayDevice.getHwvtepNodeId();
+ String elanInstanceName = elanInstance.getElanInstanceName();
+ LOG.debug("running assosiate l2gw connection job for {} {} ", elanInstanceName, hwvtepNodeId);
+
+ // Create Logical Switch if it's not created already in the device
+ if (createLogicalSwitch) {
+ LOG.info("creating logical switch {} for {} ", elanInstanceName, hwvtepNodeId);
+
+ ListenableFuture<Void> lsCreateFuture = createLogicalSwitch(l2GatewayDevice, elanInstance);
+ futures.add(lsCreateFuture);
+ } else {
+ String logicalSwitchName = ElanL2GatewayUtils.getLogicalSwitchFromElan(elanInstanceName);
+ LOG.info("{} is already created in {}; adding remaining configurations", logicalSwitchName, hwvtepNodeId);
+
+ LogicalSwitchAddedJob logicalSwitchAddedJob = new LogicalSwitchAddedJob(logicalSwitchName, l2Device,
+ l2GatewayDevice, defaultVlan);
+ return logicalSwitchAddedJob.call();
+ }
+
+ return futures;
+ }
+
+ private ListenableFuture<Void> createLogicalSwitch(L2GatewayDevice l2GatewayDevice, ElanInstance elanInstance) {
+ final String logicalSwitchName = ElanL2GatewayUtils.getLogicalSwitchFromElan(
+ elanInstance.getElanInstanceName());
+ String segmentationId = elanInstance.getVni().toString();
+
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("logical switch {} is created on {} with VNI {}", logicalSwitchName,
+ l2GatewayDevice.getHwvtepNodeId(), segmentationId);
+ }
+ NodeId hwvtepNodeId = new NodeId(l2GatewayDevice.getHwvtepNodeId());
+ InstanceIdentifier<LogicalSwitches> path = HwvtepSouthboundUtils
+ .createLogicalSwitchesInstanceIdentifier(hwvtepNodeId, new HwvtepNodeName(logicalSwitchName));
+ LogicalSwitches logicalSwitch = HwvtepSouthboundUtils.createLogicalSwitch(logicalSwitchName,
+ elanInstance.getDescription(), segmentationId);
+
+ ListenableFuture<Void> lsCreateFuture = HwvtepUtils.addLogicalSwitch(broker, hwvtepNodeId, logicalSwitch);
+ Futures.addCallback(lsCreateFuture, new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(Void noarg) {
+ // Listener will be closed after all configuration completed
+ // on hwvtep by
+ // listener itself
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Successful in initiating logical switch {} creation", logicalSwitchName);
+ }
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ LOG.error("Failed logical switch {} creation", logicalSwitchName, error);
+ }
+ });
+ return lsCreateFuture;
+ }
+}
--- /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.l2gw.jobs;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentMap;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.elanmanager.utils.ElanL2GwCacheUtils;
+import org.opendaylight.vpnservice.elan.l2gw.utils.ElanL2GatewayUtils;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * The Job class to delete L2 gateway device local ucast macs from other Elan L2
+ * gateway devices.
+ */
+public class DeleteL2GwDeviceMacsFromElanJob implements Callable<List<ListenableFuture<Void>>> {
+
+ /** The Constant JOB_KEY_PREFIX. */
+ private static final String JOB_KEY_PREFIX = "hwvtep:";
+
+ /** The Constant LOG. */
+ private static final Logger LOG = LoggerFactory.getLogger(DeleteL2GwDeviceMacsFromElanJob.class);
+
+ /** The broker. */
+ private final DataBroker broker;
+
+ /** The elan name. */
+ private final String elanName;
+
+ /** The l2 gw device. */
+ private final L2GatewayDevice l2GwDevice;
+
+ /** The mac addresses. */
+ private final List<MacAddress> macAddresses;
+
+ /**
+ * Instantiates a new delete l2 gw device macs from elan job.
+ *
+ * @param broker
+ * the broker
+ * @param elanName
+ * the elan name
+ * @param l2GwDevice
+ * the l2 gw device
+ * @param macAddresses
+ * the mac addresses
+ */
+ public DeleteL2GwDeviceMacsFromElanJob(DataBroker broker, String elanName, L2GatewayDevice l2GwDevice,
+ List<MacAddress> macAddresses) {
+ this.broker = broker;
+ this.elanName = elanName;
+ this.l2GwDevice = l2GwDevice;
+ this.macAddresses = macAddresses;
+ }
+
+ public String getJobKey() {
+ return JOB_KEY_PREFIX + this.elanName;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.concurrent.Callable#call()
+ */
+ @Override
+ public List<ListenableFuture<Void>> call() {
+ LOG.debug("Deleting l2gw device [{}] macs from other l2gw devices for elan [{}]",
+ this.l2GwDevice.getHwvtepNodeId(), this.elanName);
+ final String logicalSwitchName = ElanL2GatewayUtils.getLogicalSwitchFromElan(this.elanName);
+
+ ConcurrentMap<String, L2GatewayDevice> elanL2GwDevices = ElanL2GwCacheUtils
+ .getInvolvedL2GwDevices(this.elanName);
+ List<ListenableFuture<Void>> futures = Lists.newArrayList();
+ for (L2GatewayDevice otherDevice : elanL2GwDevices.values()) {
+ if (!otherDevice.getHwvtepNodeId().equals(this.l2GwDevice.getHwvtepNodeId())
+ && !ElanL2GatewayUtils.areMLAGDevices(this.l2GwDevice, otherDevice)) {
+ final String hwvtepId = otherDevice.getHwvtepNodeId();
+ // never batch deletes
+ ListenableFuture<Void> uninstallFuture = HwvtepUtils.deleteRemoteUcastMacs(this.broker,
+ new NodeId(hwvtepId), logicalSwitchName, this.macAddresses);
+ Futures.addCallback(uninstallFuture, new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(Void noarg) {
+ LOG.trace("Successful in initiating ucast_remote_macs deletion related to {} in {}",
+ logicalSwitchName, hwvtepId);
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ LOG.error(String.format("Failed removing ucast_remote_macs related to %s in %s",
+ logicalSwitchName, hwvtepId), error);
+ }
+ });
+ // TODO: why to create a new arraylist for uninstallFuture?
+ futures.addAll(Lists.newArrayList(uninstallFuture));
+ }
+ }
+ return futures;
+ }
+}
--- /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.l2gw.jobs;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.vpnservice.elan.l2gw.utils.ElanL2GatewayMulticastUtils;
+import org.opendaylight.vpnservice.elan.l2gw.utils.ElanL2GatewayUtils;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.Devices;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+/**
+* Created by ekvsver on 4/15/2016.
+*/
+public class DisAssociateHwvtepFromElanJob implements Callable<List<ListenableFuture<Void>>> {
+ DataBroker broker;
+ L2GatewayDevice l2GatewayDevice;
+ ElanInstance elanInstance;
+ Devices l2Device;
+ Integer defaultVlan;
+ boolean isLastL2GwConnDeleted;
+
+ private static final Logger LOG = LoggerFactory.getLogger(DisAssociateHwvtepFromElanJob.class);
+
+ public DisAssociateHwvtepFromElanJob(DataBroker broker, L2GatewayDevice l2GatewayDevice, ElanInstance elanInstance,
+ Devices l2Device, Integer defaultVlan, boolean isLastL2GwConnDeleted) {
+ this.broker = broker;
+ this.l2GatewayDevice = l2GatewayDevice;
+ this.elanInstance = elanInstance;
+ this.l2Device = l2Device;
+ this.defaultVlan = defaultVlan;
+ this.isLastL2GwConnDeleted = isLastL2GwConnDeleted;
+ LOG.info("created disassosiate l2gw connection job for {} {}", elanInstance.getElanInstanceName(),
+ l2GatewayDevice.getHwvtepNodeId());
+ }
+
+ public String getJobKey() {
+ return elanInstance.getElanInstanceName();
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ String elanName = elanInstance.getElanInstanceName();
+ String strHwvtepNodeId = l2GatewayDevice.getHwvtepNodeId();
+ NodeId hwvtepNodeId = new NodeId(strHwvtepNodeId);
+ LOG.info("running disassosiate l2gw connection job for {} {}", elanName, strHwvtepNodeId);
+
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+
+ // Remove remote MACs and vlan mappings from physical port
+ // Once all above configurations are deleted, delete logical
+ // switch
+ LOG.info("delete vlan bindings for {} {}", elanName, strHwvtepNodeId);
+ futures.add(ElanL2GatewayUtils.deleteVlanBindingsFromL2GatewayDevice(hwvtepNodeId, l2Device, defaultVlan));
+
+ if (isLastL2GwConnDeleted) {
+ LOG.info("delete remote ucast macs {} {}", elanName, strHwvtepNodeId);
+ futures.add(ElanL2GatewayUtils.deleteElanMacsFromL2GatewayDevice(l2GatewayDevice, elanName));
+
+ LOG.info("delete mcast mac for {} {}", elanName, strHwvtepNodeId);
+ futures.addAll(ElanL2GatewayMulticastUtils.handleMcastForElanL2GwDeviceDelete(elanInstance,
+ l2GatewayDevice));
+
+ LOG.info("delete local ucast macs {} {}", elanName, strHwvtepNodeId);
+ futures.addAll(ElanL2GatewayUtils.deleteL2GwDeviceUcastLocalMacsFromElan(l2GatewayDevice, elanName));
+
+ LOG.info("scheduled delete logical switch {} {}", elanName, strHwvtepNodeId);
+ ElanL2GatewayUtils.scheduleDeleteLogicalSwitch(hwvtepNodeId,
+ ElanL2GatewayUtils.getLogicalSwitchFromElan(elanName));
+ }
+
+ return futures;
+ }
+}
--- /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.l2gw.jobs;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import org.opendaylight.vpnservice.elan.l2gw.utils.ElanL2GatewayMulticastUtils;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class HwvtepDeviceMcastMacUpdateJob implements Callable<List<ListenableFuture<Void>>> {
+ private static final Logger LOG = LoggerFactory.getLogger(HwvtepDeviceMcastMacUpdateJob.class);
+
+ String elanName;
+ L2GatewayDevice l2GatewayDevice;
+
+ public HwvtepDeviceMcastMacUpdateJob(String elanName, L2GatewayDevice l2GatewayDevice) {
+ this.l2GatewayDevice = l2GatewayDevice;
+ this.elanName = elanName;
+ }
+
+ public String getJobKey() {
+ return elanName;
+ }
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ LOG.info("running update mcast mac entry job for {} {}",
+ elanName, l2GatewayDevice.getHwvtepNodeId());
+ return Lists.newArrayList(
+ ElanL2GatewayMulticastUtils.updateRemoteMcastMacOnElanL2GwDevice(elanName, l2GatewayDevice));
+ }
+
+}
--- /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.l2gw.jobs;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import org.opendaylight.vpnservice.elan.l2gw.listeners.HwvtepRemoteMcastMacListener;
+import org.opendaylight.vpnservice.elan.l2gw.utils.ElanL2GatewayMulticastUtils;
+import org.opendaylight.vpnservice.elan.l2gw.utils.ElanL2GatewayUtils;
+import org.opendaylight.vpnservice.elan.utils.ElanUtils;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.Devices;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * The Class LogicalSwitchAddedWorker.
+ */
+public class LogicalSwitchAddedJob implements Callable<List<ListenableFuture<Void>>> {
+ /** The logical switch name. */
+ private String logicalSwitchName;
+
+ /** The physical device. */
+ private Devices physicalDevice;
+
+ /** The l2 gateway device. */
+ private L2GatewayDevice elanL2GwDevice;
+
+ /** The default vlan id. */
+ private Integer defaultVlanId;
+
+ private static final Logger LOG = LoggerFactory.getLogger(LogicalSwitchAddedJob.class);
+
+ public LogicalSwitchAddedJob(String logicalSwitchName, Devices physicalDevice, L2GatewayDevice l2GatewayDevice,
+ Integer defaultVlanId) {
+ this.logicalSwitchName = logicalSwitchName;
+ this.physicalDevice = physicalDevice;
+ this.elanL2GwDevice = l2GatewayDevice;
+ this.defaultVlanId = defaultVlanId;
+ LOG.debug("created logical switch added job for {} {}", logicalSwitchName, elanL2GwDevice.getHwvtepNodeId());
+ }
+
+ public String getJobKey() {
+ return logicalSwitchName;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.concurrent.Callable#call()
+ */
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ try {
+ LOG.debug("running logical switch added job for {} {}", logicalSwitchName, elanL2GwDevice.getHwvtepNodeId());
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ String elan = ElanL2GatewayUtils.getElanFromLogicalSwitch(logicalSwitchName);
+
+ LOG.info("creating vlan bindings for {} {}", logicalSwitchName, elanL2GwDevice.getHwvtepNodeId());
+ futures.add(ElanL2GatewayUtils.updateVlanBindingsInL2GatewayDevice(
+ new NodeId(elanL2GwDevice.getHwvtepNodeId()), logicalSwitchName, physicalDevice, defaultVlanId));
+ LOG.info("creating mast mac entries for {} {}", logicalSwitchName, elanL2GwDevice.getHwvtepNodeId());
+ futures.add(ElanL2GatewayMulticastUtils.handleMcastForElanL2GwDeviceAdd(logicalSwitchName, elanL2GwDevice));
+
+ List<IpAddress> expectedPhyLocatorIps = Lists.newArrayList();
+ HwvtepRemoteMcastMacListener list = new HwvtepRemoteMcastMacListener(ElanUtils.getDataBroker(),
+ logicalSwitchName, elanL2GwDevice, expectedPhyLocatorIps,
+ new Callable<List<ListenableFuture<Void>>>() {
+ @Override
+ public List<ListenableFuture<Void>> call() {
+ LOG.info("adding remote ucast macs for {} {}", logicalSwitchName,
+ elanL2GwDevice.getHwvtepNodeId());
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ futures.add(ElanL2GatewayUtils.installElanMacsInL2GatewayDevice(
+ logicalSwitchName, elanL2GwDevice));
+ return futures;
+ }
+ });
+
+ return futures;
+ } catch (Throwable e) {
+ LOG.error("failed to add ls ", e);
+ 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.l2gw.jobs;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepUtils;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+/**
+ * The Class LogicalSwitchDeletedJob.
+ */
+public class LogicalSwitchDeletedJob implements Callable<List<ListenableFuture<Void>>> {
+ private DataBroker broker;
+
+ /** The logical switch name. */
+ private String logicalSwitchName;
+
+ /** The physical device. */
+ private NodeId hwvtepNodeId;
+
+ private static final Logger LOG = LoggerFactory.getLogger(LogicalSwitchDeletedJob.class);
+
+ public LogicalSwitchDeletedJob(DataBroker broker, NodeId hwvtepNodeId, String logicalSwitchName) {
+ this.broker = broker;
+ this.hwvtepNodeId = hwvtepNodeId;
+ this.logicalSwitchName = logicalSwitchName;
+ LOG.debug("created logical switch deleted job for {} on {}", logicalSwitchName, hwvtepNodeId);
+ }
+
+ public String getJobKey() {
+ return logicalSwitchName;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.concurrent.Callable#call()
+ */
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ try {
+ LOG.debug("running logical switch deleted job for {} in {}", logicalSwitchName, hwvtepNodeId);
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ futures.add(HwvtepUtils.deleteLogicalSwitch(broker, hwvtepNodeId, logicalSwitchName));
+ return futures;
+ } catch (Throwable e) {
+ LOG.error("failed to delete ls ", e);
+ 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.l2gw.listeners;
+
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
+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.elanmanager.utils.ElanL2GwCacheUtils;
+import org.opendaylight.vpnservice.datastoreutils.AsyncClusteredDataChangeListenerBase;
+import org.opendaylight.vpnservice.elan.l2gw.utils.ElanL2GatewayUtils;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+
+/**
+ * A listener for Ucast MAC entries that are added/removed to/from an External Device (e.g., TOR).
+ *
+ * When a Ucast MAC addr appears in the hwvtep's operational DS, that MAC must be populated in DMAC tables in all
+ * Elan participating DPNs. ELAN is selected according to field 'tunnel_key' of the Logical Switch to which the new
+ * MAC belongs.
+ *
+ */
+public class HwvtepLocalUcastMacListener extends
+ AsyncClusteredDataChangeListenerBase<LocalUcastMacs, HwvtepLocalUcastMacListener> implements AutoCloseable {
+
+ private DataBroker broker;
+ private ListenerRegistration<DataChangeListener> lstnerRegistration;
+
+ private static final Logger logger = LoggerFactory.getLogger(HwvtepLocalUcastMacListener.class);
+
+ public HwvtepLocalUcastMacListener(DataBroker broker) {
+ super(LocalUcastMacs.class, HwvtepLocalUcastMacListener.class);
+
+ this.broker = broker;
+ registerListener();
+ }
+
+ protected void registerListener() {
+ try {
+ lstnerRegistration = this.broker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ HwvtepUtils.getWildCardPathForLocalUcastMacs(), this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ logger.error("Hwvtep LocalUcasMacs DataChange listener registration failed !", e);
+ throw new IllegalStateException("Hwvtep LocalUcasMacs DataChange listener registration failed .", e);
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (lstnerRegistration != null) {
+ try {
+ lstnerRegistration.close();
+ } catch (final Exception e) {
+ logger.error("Error when cleaning up DataChangeListener.", e);
+ }
+ lstnerRegistration = null;
+ }
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<LocalUcastMacs> identifier, LocalUcastMacs macRemoved) {
+ String hwvtepNodeId = identifier.firstKeyOf(Node.class).getNodeId().getValue();
+ String macAddress = macRemoved.getMacEntryKey().getValue();
+
+ logger.trace("LocalUcastMacs {} removed from {}", macAddress, hwvtepNodeId);
+
+ ElanInstance elan = ElanL2GatewayUtils.getElanInstanceForUcastLocalMac(macRemoved);
+ if (elan == null) {
+ logger.warn("Could not find ELAN for mac {} being deleted", macAddress);
+ return;
+ }
+
+ String elanName = elan.getElanInstanceName();
+ L2GatewayDevice elanL2GwDevice = ElanL2GwCacheUtils.getL2GatewayDeviceFromCache(elanName, hwvtepNodeId);
+ if (elanL2GwDevice == null) {
+ logger.warn("Could not find L2GatewayDevice for ELAN: {}, nodeID:{} from cache", elanName, hwvtepNodeId);
+ return;
+ }
+
+ // Remove MAC from cache
+ elanL2GwDevice.removeUcastLocalMac(macRemoved);
+
+ ElanL2GatewayUtils.unInstallL2GwUcastMacFromElan(elan, elanL2GwDevice,
+ Lists.newArrayList(macRemoved.getMacEntryKey()));
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<LocalUcastMacs> identifier, LocalUcastMacs original,
+ LocalUcastMacs update) {
+ // TODO (eperefr) what can change here?
+
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<LocalUcastMacs> identifier, LocalUcastMacs macAdded) {
+ String hwvtepNodeId = identifier.firstKeyOf(Node.class).getNodeId().getValue();
+ String macAddress = macAdded.getMacEntryKey().getValue();
+
+ logger.trace("LocalUcastMacs {} added to {}", macAddress, hwvtepNodeId);
+
+ ElanInstance elan = ElanL2GatewayUtils.getElanInstanceForUcastLocalMac(macAdded);
+ if (elan == null) {
+ logger.warn("Could not find ELAN for mac {} being added", macAddress);
+ return;
+ }
+
+ String elanName = elan.getElanInstanceName();
+ L2GatewayDevice elanL2GwDevice = ElanL2GwCacheUtils.getL2GatewayDeviceFromCache(elanName, hwvtepNodeId);
+ if (elanL2GwDevice == null) {
+ logger.warn("Could not find L2GatewayDevice for ELAN: {}, nodeID:{} from cache", elanName, hwvtepNodeId);
+ return;
+ }
+
+ // Cache MAC for furthur processing later
+ elanL2GwDevice.addUcastLocalMac(macAdded);
+
+ ElanL2GatewayUtils.installL2GwUcastMacInElan(elan, elanL2GwDevice, macAddress);
+ }
+
+ @Override
+ protected InstanceIdentifier<LocalUcastMacs> getWildCardPath() {
+ return InstanceIdentifier.create(LocalUcastMacs.class);
+ }
+
+ @Override
+ protected ClusteredDataChangeListener getDataChangeListener() {
+ return HwvtepLocalUcastMacListener.this;
+ }
+
+ @Override
+ protected DataChangeScope getDataChangeScope() {
+ return DataChangeScope.BASE;
+ }
+}
--- /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.l2gw.listeners;
+
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.elan.l2gw.jobs.LogicalSwitchAddedJob;
+import org.opendaylight.vpnservice.elan.l2gw.utils.L2GatewayConnectionUtils;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.vpnservice.utils.SystemPropertyReader;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepSouthboundUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.Devices;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The listener class for listening to {@code LogicalSwitches}
+ * add/delete/update.
+ *
+ * @see LogicalSwitches
+ */
+public class HwvtepLogicalSwitchListener
+ extends AsyncDataChangeListenerBase<LogicalSwitches, HwvtepLogicalSwitchListener> {
+
+ /** The Constant LOG. */
+ private static final Logger LOG = LoggerFactory.getLogger(HwvtepLogicalSwitchListener.class);
+
+ /** The node id. */
+ private NodeId nodeId;
+
+ /** The logical switch name. */
+ private String logicalSwitchName;
+
+ /** The physical device. */
+ private Devices physicalDevice;
+
+ /** The l2 gateway device. */
+ private L2GatewayDevice l2GatewayDevice;
+
+ /** The default vlan id. */
+ private Integer defaultVlanId;
+
+ /** Id of L2 Gateway connection responsible for this logical switch creation */
+ private Uuid l2GwConnId;
+
+ static DataStoreJobCoordinator dataStoreJobCoordinator;
+
+ public static void setDataStoreJobCoordinator(DataStoreJobCoordinator ds) {
+ dataStoreJobCoordinator = ds;
+ }
+
+ /**
+ * Instantiates a new hardware vtep logical switch listener.
+ *
+ * @param l2GatewayDevice
+ * the l2 gateway device
+ * @param logicalSwitchName
+ * the logical switch name
+ * @param physicalDevice
+ * the physical device
+ * @param defaultVlanId
+ * the default vlan id
+ * @param l2GwConnId
+ * the l2 gateway connection id
+ */
+ public HwvtepLogicalSwitchListener(L2GatewayDevice l2GatewayDevice, String logicalSwitchName,
+ Devices physicalDevice, Integer defaultVlanId, Uuid l2GwConnId) {
+ super(LogicalSwitches.class, HwvtepLogicalSwitchListener.class);
+ this.nodeId = new NodeId(l2GatewayDevice.getHwvtepNodeId());
+ this.logicalSwitchName = logicalSwitchName;
+ this.physicalDevice = physicalDevice;
+ this.l2GatewayDevice = l2GatewayDevice;
+ this.defaultVlanId = defaultVlanId;
+ this.l2GwConnId = l2GwConnId;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase#
+ * getWildCardPath()
+ */
+ @Override
+ public InstanceIdentifier<LogicalSwitches> getWildCardPath() {
+ return HwvtepSouthboundUtils.createLogicalSwitchesInstanceIdentifier(nodeId,
+ new HwvtepNodeName(logicalSwitchName));
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase#
+ * getDataChangeListener()
+ */
+ @Override
+ protected DataChangeListener getDataChangeListener() {
+ return HwvtepLogicalSwitchListener.this;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase#
+ * getDataChangeScope()
+ */
+ @Override
+ protected AsyncDataBroker.DataChangeScope getDataChangeScope() {
+ return AsyncDataBroker.DataChangeScope.BASE;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase#
+ * remove(org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
+ * org.opendaylight.yangtools.yang.binding.DataObject)
+ */
+ @Override
+ protected void remove(InstanceIdentifier<LogicalSwitches> identifier, LogicalSwitches deletedLogicalSwitch) {
+ LOG.trace("Received Remove DataChange Notification for identifier: {}, LogicalSwitches: {}", identifier,
+ deletedLogicalSwitch);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase#
+ * update(org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
+ * org.opendaylight.yangtools.yang.binding.DataObject,
+ * org.opendaylight.yangtools.yang.binding.DataObject)
+ */
+ @Override
+ protected void update(InstanceIdentifier<LogicalSwitches> identifier, LogicalSwitches logicalSwitchOld,
+ LogicalSwitches logicalSwitchNew) {
+ LOG.trace("Received Update DataChange Notification for identifier: {}, LogicalSwitches old: {}, new: {}."
+ + "No Action Performed.", identifier, logicalSwitchOld, logicalSwitchNew);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase#
+ * add(org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
+ * org.opendaylight.yangtools.yang.binding.DataObject)
+ */
+ @Override
+ protected void add(InstanceIdentifier<LogicalSwitches> identifier, LogicalSwitches logicalSwitchNew) {
+ LOG.debug("Received Add DataChange Notification for identifier: {}, LogicalSwitches: {}", identifier,
+ logicalSwitchNew);
+ try {
+ L2GatewayDevice elanDevice = L2GatewayConnectionUtils.addL2DeviceToElanL2GwCache(
+ logicalSwitchNew.getHwvtepNodeName().getValue(), l2GatewayDevice, l2GwConnId);
+
+ LogicalSwitchAddedJob logicalSwitchAddedWorker = new LogicalSwitchAddedJob(
+ logicalSwitchName, physicalDevice, elanDevice, defaultVlanId);
+ dataStoreJobCoordinator.enqueueJob(logicalSwitchAddedWorker.getJobKey(), logicalSwitchAddedWorker,
+ SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
+
+ } catch (Exception e) {
+ LOG.error("Failed to handle HwVTEPLogicalSwitch - add: {}", e);
+ } finally {
+ try {
+ // This listener is specific to handle a specific logical
+ // switch, hence closing it.
+ LOG.trace("Closing LogicalSwitches listener for node: {}, logicalSwitch: {}", nodeId.getValue(),
+ logicalSwitchName);
+ close();
+ } catch (Exception e) {
+ LOG.warn("Failed to close HwVTEPLogicalSwitchListener: {}", e);
+ }
+ }
+ }
+
+}
\ 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.l2gw.listeners;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.elanmanager.utils.ElanL2GwCacheUtils;
+import org.opendaylight.vpnservice.datastoreutils.AsyncClusteredDataChangeListenerBase;
+import org.opendaylight.vpnservice.elan.internal.ElanInstanceManager;
+import org.opendaylight.vpnservice.elan.l2gw.utils.ElanL2GatewayUtils;
+import org.opendaylight.vpnservice.elan.l2gw.utils.L2GatewayConnectionUtils;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.utils.L2GatewayCacheUtils;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepSouthboundConstants;
+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.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.connections.attributes.L2gatewayConnections;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.connections.attributes.l2gatewayconnections.L2gatewayConnection;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelIps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class HwvtepNodeListener
+ extends AsyncClusteredDataChangeListenerBase<Node, HwvtepNodeListener> {
+ private static final Logger LOG = LoggerFactory.getLogger(HwvtepNodeListener.class);
+
+ private DataBroker dataBroker;
+ private ItmRpcService itmRpcService;
+ ElanInstanceManager elanInstanceManager;
+
+ public HwvtepNodeListener(final DataBroker dataBroker, ElanInstanceManager elanInstanceManager,
+ ItmRpcService itmRpcService) {
+ super(Node.class, HwvtepNodeListener.class);
+ this.dataBroker = dataBroker;
+ this.itmRpcService = itmRpcService;
+ this.elanInstanceManager = elanInstanceManager;
+ }
+
+ @Override
+ protected InstanceIdentifier<Node> getWildCardPath() {
+ return InstanceIdentifier.create(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID)).child(Node.class);
+ }
+
+ @Override
+ protected HwvtepNodeListener getDataChangeListener() {
+ return HwvtepNodeListener.this;
+ }
+
+ @Override
+ protected DataChangeScope getDataChangeScope() {
+ return AsyncDataBroker.DataChangeScope.BASE;
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Node> key, Node nodeDeleted) {
+ String nodeId = nodeDeleted.getNodeId().getValue();
+ LOG.debug("Received Node Remove Event for {}", nodeId);
+
+ PhysicalSwitchAugmentation psAugmentation = nodeDeleted.getAugmentation(PhysicalSwitchAugmentation.class);
+ if (psAugmentation != null) {
+ String psName = psAugmentation.getHwvtepNodeName().getValue();
+ LOG.info("Physical switch {} removed from node {} event received", psName, nodeId);
+
+ L2GatewayDevice l2GwDevice = L2GatewayCacheUtils.getL2DeviceFromCache(psName);
+ if (l2GwDevice != null) {
+ if (!L2GatewayConnectionUtils.isGatewayAssociatedToL2Device(l2GwDevice)) {
+ L2GatewayCacheUtils.removeL2DeviceFromCache(psName);
+ LOG.debug("{} details removed from L2Gateway Cache", psName);
+ } else {
+ LOG.debug("{} details are not removed from L2Gateway Cache as it has L2Gateway refrence", psName);
+ }
+
+ l2GwDevice.setConnected(false);
+ ElanL2GwCacheUtils.removeL2GatewayDeviceFromAllElanCache(psName);
+ } else {
+ LOG.error("Unable to find L2 Gateway details for {}", psName);
+ }
+ } else {
+ LOG.trace("Received Node Remove Event for {} is not related to Physical switch; it's not processed",
+ nodeId);
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Node> key, Node nodeBefore, Node nodeAfter) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Received Node Update Event: Node Before: {}, Node After: {}", nodeBefore, nodeAfter);
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Node> key, Node nodeAdded) {
+ String nodeId = nodeAdded.getNodeId().getValue();
+ LOG.debug("Received Node Add Event for {}", nodeId);
+
+ PhysicalSwitchAugmentation psAugmentation = nodeAdded.getAugmentation(PhysicalSwitchAugmentation.class);
+ if (psAugmentation != null) {
+ String psName = psAugmentation.getHwvtepNodeName().getValue();
+ LOG.info("Physical switch {} added to node {} event received", psName, nodeId);
+
+ L2GatewayDevice l2GwDevice = L2GatewayCacheUtils.getL2DeviceFromCache(psName);
+ if (l2GwDevice == null) {
+ LOG.debug("{} details are not present in L2Gateway Cache; added now!", psName);
+
+ l2GwDevice = new L2GatewayDevice();
+ l2GwDevice.setDeviceName(psName);
+ L2GatewayCacheUtils.addL2DeviceToCache(psName, l2GwDevice);
+ } else {
+ LOG.debug("{} details are present in L2Gateway Cache and same reference used for updates", psName);
+ }
+
+ l2GwDevice.setConnected(true);
+ String hwvtepNodeId = getManagedByNodeId(psAugmentation.getManagedBy());
+ l2GwDevice.setHwvtepNodeId(hwvtepNodeId);
+ List<TunnelIps> tunnelIps = psAugmentation.getTunnelIps();
+ if (tunnelIps != null) {
+ for (TunnelIps tunnelIp : tunnelIps) {
+ IpAddress tunnelIpAddr = tunnelIp.getTunnelIpsKey();
+ l2GwDevice.addTunnelIp(tunnelIpAddr);
+ if (L2GatewayConnectionUtils.isGatewayAssociatedToL2Device(l2GwDevice)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("L2Gateway {} associated for {} physical switch; creating ITM tunnels for {}",
+ l2GwDevice.getL2GatewayIds(), psName, tunnelIpAddr);
+ }
+
+ // It's a pre-provision scenario
+ // Initiate ITM tunnel creation
+ ElanL2GatewayUtils.createItmTunnels(itmRpcService, hwvtepNodeId, psName, tunnelIpAddr);
+
+ // Initiate Logical switch creation for associated L2
+ // Gateway Connections
+ List<L2gatewayConnection> l2GwConns = getAssociatedL2GwConnections(dataBroker,
+ l2GwDevice.getL2GatewayIds());
+ if (l2GwConns != null) {
+ LOG.debug("L2GatewayConnections associated for {} physical switch", psName);
+
+ for (L2gatewayConnection l2GwConn : l2GwConns) {
+ LOG.trace("L2GatewayConnection {} changes executed on physical switch {}",
+ l2GwConn.getL2gatewayId(), psName);
+
+ L2GatewayConnectionUtils.addL2GatewayConnection(l2GwConn, psName);
+ }
+ }
+ //TODO handle deleted l2gw connections while the device is offline
+ }
+ }
+ }
+
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("L2Gateway cache updated with below details: {}", l2GwDevice);
+ }
+ } else {
+ LOG.trace("Received Node Add Event for {} is not related to Physical switch; it's not processed", nodeId);
+ }
+ }
+
+ private List<L2gatewayConnection> getAssociatedL2GwConnections(DataBroker broker, List<Uuid> l2GatewayIds) {
+ List<L2gatewayConnection> l2GwConnections = null;
+ List<L2gatewayConnection> allL2GwConns = getAllL2gatewayConnections(broker);
+ if (allL2GwConns != null) {
+ l2GwConnections = new ArrayList<L2gatewayConnection>();
+ for (Uuid l2GatewayId : l2GatewayIds) {
+ for (L2gatewayConnection l2GwConn : allL2GwConns) {
+ if (l2GwConn.getL2gatewayId().equals(l2GatewayId)) {
+ l2GwConnections.add(l2GwConn);
+ }
+ }
+ }
+ }
+ return l2GwConnections;
+ }
+
+ protected List<L2gatewayConnection> getAllL2gatewayConnections(DataBroker broker) {
+ InstanceIdentifier<L2gatewayConnections> inst = InstanceIdentifier.create(Neutron.class)
+ .child(L2gatewayConnections.class);
+ Optional<L2gatewayConnections> l2GwConns = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, inst);
+ if (l2GwConns.isPresent()) {
+ return l2GwConns.get().getL2gatewayConnection();
+ }
+ return null;
+ }
+
+ private String getManagedByNodeId(HwvtepGlobalRef globalRef) {
+ InstanceIdentifier<?> instId = globalRef.getValue();
+ return instId.firstKeyOf(Node.class, NodeKey.class).getNodeId().getValue();
+ }
+}
--- /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.l2gw.listeners;
+
+import com.google.common.collect.Lists;
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataChangeListener;
+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.datastoreutils.AsyncClusteredDataChangeListenerBase;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+
+/**
+ * Listener for physical locator presence in operational datastore
+ *
+ *
+ *
+ */
+public class HwvtepPhysicalLocatorListener extends
+ AsyncClusteredDataChangeListenerBase<TerminationPoint, HwvtepPhysicalLocatorListener> implements AutoCloseable {
+
+ private DataBroker broker;
+ private ListenerRegistration<DataChangeListener> lstnerRegistration;
+
+ private static final Logger logger = LoggerFactory.getLogger(HwvtepPhysicalLocatorListener.class);
+
+ public HwvtepPhysicalLocatorListener(DataBroker broker) {
+ super(TerminationPoint.class, HwvtepPhysicalLocatorListener.class);
+
+ this.broker = broker;
+ registerListener();
+ logger.debug("created HwvtepPhysicalLocatorListener");
+ }
+
+ static Map<InstanceIdentifier<TerminationPoint>, List<Runnable>> waitingJobsList = new ConcurrentHashMap<>();
+ static Map<InstanceIdentifier<TerminationPoint>, Boolean> teps = new ConcurrentHashMap<>();
+
+ public static void runJobAfterPhysicalLocatorIsAvialable(InstanceIdentifier<TerminationPoint> key, Runnable runnable) {
+ if (teps.get(key) != null) {
+ logger.debug("physical locator already available {} running job ", key);
+ runnable.run();
+ return;
+ }
+ synchronized (HwvtepPhysicalLocatorListener.class) {
+ List<Runnable> list = waitingJobsList.get(key);
+ if (list == null) {
+ waitingJobsList.put(key, Lists.newArrayList(runnable));
+ } else {
+ list.add(runnable);
+ }
+ logger.debug("added the job to wait list of physical locator {}", key);
+ }
+ }
+
+ protected void registerListener() {
+ try {
+ lstnerRegistration = this.broker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ InstanceIdentifier.create(NetworkTopology.class).child(Topology.class).child(Node.class).
+ child(TerminationPoint.class), this, DataChangeScope.BASE);
+ } catch (final Exception e) {
+ logger.error("Hwvtep LocalUcasMacs DataChange listener registration failed !", e);
+ throw new IllegalStateException("Hwvtep LocalUcasMacs DataChange listener registration failed .", e);
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (lstnerRegistration != null) {
+ try {
+ lstnerRegistration.close();
+ } catch (final Exception e) {
+ logger.error("Error when cleaning up DataChangeListener.", e);
+ }
+ lstnerRegistration = null;
+ }
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<TerminationPoint> identifier, TerminationPoint del) {
+ logger.trace("physical locator removed {}", identifier);
+ teps.remove(identifier);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<TerminationPoint> identifier, TerminationPoint original, TerminationPoint update) {
+ logger.trace("physical locator available {}", identifier);
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<TerminationPoint> identifier, TerminationPoint add) {
+ logger.trace("physical locator available {}", identifier);
+ teps.put(identifier, true);
+ List<Runnable> runnableList = null;
+ synchronized (HwvtepPhysicalLocatorListener.class) {
+ runnableList = waitingJobsList.get(identifier);
+ waitingJobsList.remove(identifier);
+ }
+ if (runnableList != null) {
+ logger.debug("physical locator available {} running jobs ", identifier);
+ for (Runnable r : runnableList) {
+ r.run();
+ }
+ } else {
+ logger.debug("no jobs are waiting for physical locator {}", identifier);
+ }
+ }
+
+ @Override
+ protected InstanceIdentifier<TerminationPoint> getWildCardPath() {
+ return InstanceIdentifier.create(NetworkTopology.class).child(Topology.class).child(Node.class).
+ child(TerminationPoint.class);
+ }
+
+ @Override
+ protected ClusteredDataChangeListener getDataChangeListener() {
+ return HwvtepPhysicalLocatorListener.this;
+ }
+
+ @Override
+ protected DataChangeScope getDataChangeScope() {
+ return DataChangeScope.BASE;
+ }
+}
--- /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.l2gw.listeners;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+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.datastoreutils.AsyncDataChangeListenerBase;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.elan.l2gw.utils.ElanL2GatewayUtils;
+import org.opendaylight.vpnservice.elan.utils.ElanConstants;
+import org.opendaylight.vpnservice.elan.utils.ElanUtils;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.vpnservice.utils.SystemPropertyReader;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepSouthboundUtils;
+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.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * The listener class for listening to {@code RemoteMcastMacs}
+ * add/delete/update.
+ *
+ * @see RemoteMcastMacs
+ */
+public class HwvtepRemoteMcastMacListener
+ extends AsyncDataChangeListenerBase<RemoteMcastMacs, HwvtepRemoteMcastMacListener> {
+
+ /** The Constant LOG. */
+ private static final Logger LOG = LoggerFactory.getLogger(HwvtepRemoteMcastMacListener.class);
+
+ /** The node id. */
+ private NodeId nodeId;
+
+ private List<IpAddress> expectedPhyLocatorIps;
+
+ DataBroker broker;
+
+ String logicalSwitchName;
+
+ AtomicBoolean executeTask = new AtomicBoolean(true);
+
+ Callable<List<ListenableFuture<Void>>> taskToRun;
+
+ static DataStoreJobCoordinator dataStoreJobCoordinator;
+
+ public static void setDataStoreJobCoordinator(DataStoreJobCoordinator ds) {
+ dataStoreJobCoordinator = ds;
+ }
+
+ /**
+ * Instantiates a new remote mcast mac listener.
+ *
+ * @param broker
+ * the mdsal databroker reference
+ * @param logicalSwitchName
+ * the logical switch name
+ * @param l2GatewayDevice
+ * the l2 gateway device
+ * @param expectedPhyLocatorIps
+ * the expected phy locator ips
+ * @param task
+ * the task to be run upon data presence
+ * @throws Exception
+ * the exception
+ */
+ public HwvtepRemoteMcastMacListener(DataBroker broker, String logicalSwitchName, L2GatewayDevice l2GatewayDevice,
+ List<IpAddress> expectedPhyLocatorIps, Callable<List<ListenableFuture<Void>>> task) throws Exception {
+ super(RemoteMcastMacs.class, HwvtepRemoteMcastMacListener.class);
+ this.nodeId = new NodeId(l2GatewayDevice.getHwvtepNodeId());
+ this.broker = broker;
+ this.taskToRun = task;
+ this.logicalSwitchName = logicalSwitchName;
+ this.expectedPhyLocatorIps = expectedPhyLocatorIps;
+ LOG.info("registering the listener for mcast mac ");
+ registerListener(LogicalDatastoreType.OPERATIONAL, broker);
+ LOG.info("registered the listener for mcast mac ");
+ if (isDataPresentInOpDs(getWildCardPath())) {
+ LOG.info("mcast mac already present running the task ");
+ if (executeTask.compareAndSet(true, false)) {
+ runTask();
+ }
+ }
+ }
+
+ private boolean isDataPresentInOpDs(InstanceIdentifier<RemoteMcastMacs> path) throws Exception {
+ Optional<RemoteMcastMacs> mac = null;
+ try {
+ mac = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL, path);
+ } catch (Throwable e) {
+ }
+ if (mac == null || !mac.isPresent()) {
+ return false;
+ }
+ if (this.expectedPhyLocatorIps != null && !this.expectedPhyLocatorIps.isEmpty()) {
+ RemoteMcastMacs remoteMcastMac = mac.get();
+ if (remoteMcastMac.getLocatorSet() == null || remoteMcastMac.getLocatorSet().isEmpty()) {
+ return false;
+ }
+ for (IpAddress ip : this.expectedPhyLocatorIps) {
+ boolean ipExists = ElanL2GatewayUtils.checkIfPhyLocatorAlreadyExistsInRemoteMcastEntry(this.nodeId,
+ remoteMcastMac, ip);
+ if (!ipExists) {
+ LOG.trace("IP [{}] not found in RemoteMcastMacs for node [{}]", String.valueOf(ip.getValue()),
+ this.nodeId.getValue());
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase#
+ * getWildCardPath()
+ */
+ @Override
+ public InstanceIdentifier<RemoteMcastMacs> getWildCardPath() {
+ return HwvtepSouthboundUtils.createRemoteMcastMacsInstanceIdentifier(nodeId,
+ logicalSwitchName, new MacAddress(ElanConstants.UNKNOWN_DMAC));
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase#
+ * getDataChangeListener()
+ */
+ @Override
+ protected DataChangeListener getDataChangeListener() {
+ return HwvtepRemoteMcastMacListener.this;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase#
+ * getDataChangeScope()
+ */
+ @Override
+ protected AsyncDataBroker.DataChangeScope getDataChangeScope() {
+ return AsyncDataBroker.DataChangeScope.BASE;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase#
+ * remove(org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
+ * org.opendaylight.yangtools.yang.binding.DataObject)
+ */
+ @Override
+ protected void remove(InstanceIdentifier<RemoteMcastMacs> identifier, RemoteMcastMacs deleted) {
+ LOG.trace("Received Remove DataChange Notification for identifier: {}, RemoteMcastMacs: {}", identifier,
+ deleted);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase#
+ * update(org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
+ * org.opendaylight.yangtools.yang.binding.DataObject,
+ * org.opendaylight.yangtools.yang.binding.DataObject)
+ */
+ @Override
+ protected void update(InstanceIdentifier<RemoteMcastMacs> identifier, RemoteMcastMacs old,
+ RemoteMcastMacs newdata) {
+ LOG.trace("Received Update DataChange Notification for identifier: {}, RemoteMcastMacs old: {}, new: {}."
+ + "No Action Performed.", identifier, old, newdata);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase#
+ * add(org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
+ * org.opendaylight.yangtools.yang.binding.DataObject)
+ */
+ @Override
+ protected void add(InstanceIdentifier<RemoteMcastMacs> identifier, RemoteMcastMacs mcastMac) {
+ LOG.debug("Received Add DataChange Notification for identifier: {}, RemoteMcastMacs: {}", identifier, mcastMac);
+ // No isDataPresentInOpDs check is done as assuming all the expected phy
+ // locator ips will be available during add
+ if (executeTask.compareAndSet(true, false)) {
+ runTask();
+ }
+ }
+
+ void runTask() {
+ try {
+
+ String jobKey = ElanL2GatewayUtils.getL2GatewayConnectionJobKey(nodeId.getValue(), nodeId.getValue());
+ dataStoreJobCoordinator.enqueueJob(jobKey, taskToRun, SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
+ } catch (Exception e) {
+ LOG.error("Failed to handle remote mcast mac - add: {}", e);
+ } finally {
+ try {
+ close();
+ } catch (Exception e) {
+ LOG.warn("Failed to close McastMacSwitchListener: {}", e);
+ }
+ }
+ }
+}
\ 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.l2gw.listeners;
+
+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.controller.md.sal.binding.api.ClusteredDataChangeListener;
+import org.opendaylight.vpnservice.datastoreutils.AsyncClusteredDataChangeListenerBase;
+import org.opendaylight.vpnservice.elan.internal.ElanInstanceManager;
+import org.opendaylight.vpnservice.elan.l2gw.utils.L2GatewayConnectionUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.connections.attributes.L2gatewayConnections;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.connections.attributes.l2gatewayconnections.L2gatewayConnection;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class L2GatewayConnectionListener extends AsyncClusteredDataChangeListenerBase<L2gatewayConnection,
+ L2GatewayConnectionListener> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(L2GatewayConnectionListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private ElanInstanceManager elanInstanceManager;
+
+ public L2GatewayConnectionListener(final DataBroker db, ElanInstanceManager elanInstanceManager) {
+ super(L2gatewayConnection.class, L2GatewayConnectionListener.class);
+ broker = db;
+ this.elanInstanceManager = elanInstanceManager;
+ registerListener(db);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("L2 Gateway Connection listener Closed");
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(Neutron.class).child(L2gatewayConnections.class)
+ .child(L2gatewayConnection.class),
+ L2GatewayConnectionListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("Neutron Manager L2 Gateway Connection DataChange listener registration fail!", e);
+ throw new IllegalStateException(
+ "Neutron Manager L2 Gateway Connection DataChange listener registration failed.", e);
+ }
+ }
+
+ @Override
+ protected void add(final InstanceIdentifier<L2gatewayConnection> identifier, final L2gatewayConnection input) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Adding L2gatewayConnection: {}", input);
+ }
+
+ // Get associated L2GwId from 'input'
+ // Create logical switch in each of the L2GwDevices part of L2Gw
+ // Logical switch name is network UUID
+ // Add L2GwDevices to ELAN
+ L2GatewayConnectionUtils.addL2GatewayConnection(input);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<L2gatewayConnection> identifier, L2gatewayConnection input) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Removing L2gatewayConnection: {}", input);
+ }
+
+ L2GatewayConnectionUtils.deleteL2GatewayConnection(input);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<L2gatewayConnection> identifier, L2gatewayConnection original,
+ L2gatewayConnection update) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Updating L2gatewayConnection : original value={}, updated value={}", original, update);
+ }
+ }
+
+ @Override
+ protected InstanceIdentifier<L2gatewayConnection> getWildCardPath() {
+ return InstanceIdentifier.create(L2gatewayConnection.class);
+ }
+
+ @Override
+ protected ClusteredDataChangeListener getDataChangeListener() {
+ return L2GatewayConnectionListener.this;
+ }
+
+ @Override
+ protected DataChangeScope getDataChangeScope() {
+ return DataChangeScope.BASE;
+ }
+}
--- /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.l2gw.utils;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentMap;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.elanmanager.utils.ElanL2GwCacheUtils;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.elan.internal.ElanInstanceManager;
+import org.opendaylight.vpnservice.elan.internal.ElanInterfaceManager;
+import org.opendaylight.vpnservice.elan.l2gw.jobs.HwvtepDeviceMcastMacUpdateJob;
+import org.opendaylight.vpnservice.elan.utils.ElanConstants;
+import org.opendaylight.vpnservice.elan.utils.ElanUtils;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepSouthboundUtils;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepUtils;
+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.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.dhcp.rev160428.DesignatedSwitchesForExternalTunnels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.dhcp.rev160428.designated.switches._for.external.tunnels.DesignatedSwitchForTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.dhcp.rev160428.designated.switches._for.external.tunnels.DesignatedSwitchForTunnelKey;
+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.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
+/**
+ * The utility class to handle ELAN L2 Gateway related to multicast.
+ */
+public class ElanL2GatewayMulticastUtils {
+
+ /** The Constant LOG. */
+ private static final Logger LOG = LoggerFactory.getLogger(ElanL2GatewayMulticastUtils.class);
+
+ /** The broker. */
+ private static DataBroker broker;
+
+ /** The elan instance manager. */
+ private static ElanInstanceManager elanInstanceManager;
+
+ /** The elan interface manager. */
+ private static ElanInterfaceManager elanInterfaceManager;
+
+ static DataStoreJobCoordinator dataStoreJobCoordinator;
+
+ public static void setDataStoreJobCoordinator(DataStoreJobCoordinator ds) {
+ dataStoreJobCoordinator = ds;
+ }
+
+ /**
+ * Sets the broker.
+ *
+ * @param broker
+ * the new broker
+ */
+ public static void setBroker(DataBroker broker) {
+ ElanL2GatewayMulticastUtils.broker = broker;
+ }
+
+ /**
+ * Sets the elan instance manager.
+ *
+ * @param elanMgr
+ * the new elan instance manager
+ */
+ public static void setElanInstanceManager(ElanInstanceManager elanMgr) {
+ ElanL2GatewayMulticastUtils.elanInstanceManager = elanMgr;
+ }
+
+ /**
+ * Sets the elan interface manager.
+ *
+ * @param interfaceMgr
+ * the new elan interface manager
+ */
+ public static void setElanInterfaceManager(ElanInterfaceManager interfaceMgr) {
+ elanInterfaceManager = interfaceMgr;
+ }
+
+ /**
+ * Handle mcast for elan l2 gw device add.
+ *
+ * @param elanName
+ * the elan name
+ * @param device
+ * the device
+ * @return the listenable future
+ */
+ public static ListenableFuture<Void> handleMcastForElanL2GwDeviceAdd(String elanName, L2GatewayDevice device) {
+ return updateMcastMacsForAllElanDevices(elanName, device, true/* updateThisDevice */);
+ }
+
+ /**
+ * Updates the remote mcast mac table for all the devices in this elan
+ * includes all the dpn tep ips and other devices tep ips in broadcast
+ * locator set.
+ *
+ * @param elanName
+ * the elan to be updated
+ * @return the listenable future
+ */
+ public static ListenableFuture<Void> updateRemoteMcastMacOnElanL2GwDevices(String elanName) {
+ SettableFuture<Void> future = SettableFuture.create();
+ future.set(null);
+ try {
+ WriteTransaction transaction = broker.newWriteOnlyTransaction();
+ for (L2GatewayDevice device : ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName).values()) {
+ prepareRemoteMcastMacUpdateOnDevice(transaction, elanName, device);
+ }
+ return transaction.submit();
+ } catch (Throwable e) {
+ LOG.error("Failed to configure mcast mac on elan " + elanName, e);
+ }
+ return future;
+ }
+
+ public static void scheduleMcastMacUpdateJob(String elanName, L2GatewayDevice device) {
+ HwvtepDeviceMcastMacUpdateJob job = new HwvtepDeviceMcastMacUpdateJob(elanName,device);
+ dataStoreJobCoordinator.enqueueJob(job.getJobKey(), job);
+ }
+
+ /**
+ * Update remote mcast mac on elan l2 gw device.
+ *
+ * @param elanName
+ * the elan name
+ * @param device
+ * the device
+ * @return the listenable future
+ */
+ public static ListenableFuture<Void> updateRemoteMcastMacOnElanL2GwDevice(String elanName, L2GatewayDevice device) {
+ WriteTransaction transaction = broker.newWriteOnlyTransaction();
+ prepareRemoteMcastMacUpdateOnDevice(transaction, elanName, device);
+ return transaction.submit();
+ }
+
+ public static void prepareRemoteMcastMacUpdateOnDevice(WriteTransaction transaction,String elanName,
+ L2GatewayDevice device) {
+ ConcurrentMap<String, L2GatewayDevice> elanL2gwDevices = ElanL2GwCacheUtils
+ .getInvolvedL2GwDevices(elanName);
+ List<DpnInterfaces> dpns = ElanUtils.getInvolvedDpnsInElan(elanName);
+ List<IpAddress> dpnsTepIps = getAllTepIpsOfDpns(device, dpns);
+ List<IpAddress> l2GwDevicesTepIps = getAllTepIpsOfL2GwDevices(elanL2gwDevices);
+ preapareRemoteMcastMacEntry(transaction, elanName, device, dpnsTepIps, l2GwDevicesTepIps);
+ }
+
+ /**
+ * Update mcast macs for this elan.
+ * for all dpns in this elan recompute and update broadcast group
+ * for all l2gw devices in this elan recompute and update remote mcast mac entry
+ *
+ * @param elanName
+ * the elan name
+ * @param device
+ * the device
+ * @param updateThisDevice
+ * the update this device
+ * @return the listenable future
+ */
+ public static ListenableFuture<Void> updateMcastMacsForAllElanDevices(String elanName, L2GatewayDevice device,
+ boolean updateThisDevice) {
+
+ SettableFuture<Void> ft = SettableFuture.create();
+ ft.set(null);
+
+ ElanInstance elanInstance = elanInstanceManager.getElanInstanceByName(elanName);
+ elanInterfaceManager.updateRemoteBroadcastGroupForAllElanDpns(elanInstance);
+
+ List<DpnInterfaces> dpns = ElanUtils.getInvolvedDpnsInElan(elanName);
+
+ ConcurrentMap<String, L2GatewayDevice> devices = ElanL2GwCacheUtils
+ .getInvolvedL2GwDevices(elanName);
+
+ List<IpAddress> dpnsTepIps = getAllTepIpsOfDpns(device, dpns);
+ List<IpAddress> l2GwDevicesTepIps = getAllTepIpsOfL2GwDevices(devices);
+ // if (allTepIps.size() < 2) {
+ // LOG.debug("no other devices are found in the elan {}", elanName);
+ // return ft;
+ // }
+
+ WriteTransaction transaction = broker.newWriteOnlyTransaction();
+ if (updateThisDevice) {
+ preapareRemoteMcastMacEntry(transaction, elanName, device, dpnsTepIps, l2GwDevicesTepIps);
+ }
+
+ // TODO: Need to revisit below logic as logical switches might not be
+ // present to configure RemoteMcastMac entry
+ for (L2GatewayDevice otherDevice : devices.values()) {
+ if (!otherDevice.getDeviceName().equals(device.getDeviceName())) {
+ preapareRemoteMcastMacEntry(transaction, elanName, otherDevice, dpnsTepIps, l2GwDevicesTepIps);
+ }
+ }
+ return transaction.submit();
+
+ }
+
+ /**
+ * Update remote mcast mac.
+ *
+ * @param transaction
+ * the transaction
+ * @param elanName
+ * the elan name
+ * @param device
+ * the device
+ * @param dpnsTepIps
+ * the dpns tep ips
+ * @param l2GwDevicesTepIps
+ * the l2 gw devices tep ips
+ * @return the write transaction
+ */
+ private static void preapareRemoteMcastMacEntry(WriteTransaction transaction, String elanName,
+ L2GatewayDevice device, List<IpAddress> dpnsTepIps,
+ List<IpAddress> l2GwDevicesTepIps) {
+ NodeId nodeId = new NodeId(device.getHwvtepNodeId());
+ String logicalSwitchName = ElanL2GatewayUtils.getLogicalSwitchFromElan(elanName);
+
+ ArrayList<IpAddress> remoteTepIps = new ArrayList<>(l2GwDevicesTepIps);
+ remoteTepIps.remove(device.getTunnelIp());
+ remoteTepIps.addAll(dpnsTepIps);
+ if (dpnsTepIps.isEmpty()) {
+ // If no dpns in elan, configure dhcp designated switch Tep Ip as a
+ // physical locator in l2 gw device
+ IpAddress dhcpDesignatedSwitchTepIp = getTepIpOfDesignatedSwitchForExternalTunnel(device, elanName);
+ if (dhcpDesignatedSwitchTepIp != null) {
+ remoteTepIps.add(dhcpDesignatedSwitchTepIp);
+
+ HwvtepPhysicalLocatorAugmentation phyLocatorAug = HwvtepSouthboundUtils
+ .createHwvtepPhysicalLocatorAugmentation(String.valueOf(dhcpDesignatedSwitchTepIp.getValue()));
+ HwvtepUtils.putPhysicalLocator(transaction, nodeId, phyLocatorAug);
+
+ LOG.info(
+ "Adding PhysicalLocator for node: {} with Dhcp designated switch Tep Ip {} as physical locator, elan {}",
+ device.getHwvtepNodeId(), String.valueOf(dhcpDesignatedSwitchTepIp.getValue()), elanName);
+ } else {
+ LOG.warn("Dhcp designated switch Tep Ip not found for l2 gw node {} and elan {}",
+ device.getHwvtepNodeId(), elanName);
+ }
+ }
+
+ putRemoteMcastMac(transaction, nodeId, logicalSwitchName, remoteTepIps);
+ LOG.info("Adding RemoteMcastMac for node: {} with physical locators: {}", device.getHwvtepNodeId(),
+ remoteTepIps);
+ }
+
+ /**
+ * Put remote mcast mac in config DS.
+ *
+ * @param transaction
+ * the transaction
+ * @param nodeId
+ * the node id
+ * @param logicalSwitchName
+ * the logical switch name
+ * @param tepIps
+ * the tep ips
+ */
+ private static void putRemoteMcastMac(WriteTransaction transaction, NodeId nodeId, String logicalSwitchName,
+ ArrayList<IpAddress> tepIps) {
+ List<LocatorSet> locators = new ArrayList<>();
+ for (IpAddress tepIp : tepIps) {
+ HwvtepPhysicalLocatorAugmentation phyLocatorAug = HwvtepSouthboundUtils
+ .createHwvtepPhysicalLocatorAugmentation(String.valueOf(tepIp.getValue()));
+ HwvtepPhysicalLocatorRef phyLocRef = new HwvtepPhysicalLocatorRef(
+ HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(nodeId, phyLocatorAug));
+ locators.add(new LocatorSetBuilder().setLocatorRef(phyLocRef).build());
+ }
+
+ HwvtepLogicalSwitchRef lsRef = new HwvtepLogicalSwitchRef(HwvtepSouthboundUtils
+ .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName)));
+ RemoteMcastMacs remoteUcastMac = new RemoteMcastMacsBuilder()
+ .setMacEntryKey(new MacAddress(ElanConstants.UNKNOWN_DMAC)).setLogicalSwitchRef(lsRef)
+ .setLocatorSet(locators).build();
+ HwvtepUtils.putRemoteMcastMac(transaction, nodeId, remoteUcastMac);
+ }
+
+ /**
+ * Gets all the tep ips of dpns.
+ *
+ * @param l2GwDevice
+ * the device
+ * @param dpns
+ * the dpns
+ * @return the all tep ips of dpns and devices
+ */
+ private static List<IpAddress> getAllTepIpsOfDpns(L2GatewayDevice l2GwDevice, List<DpnInterfaces> dpns) {
+ List<IpAddress> tepIps = new ArrayList<>();
+ for (DpnInterfaces dpn : dpns) {
+ IpAddress internalTunnelIp = ElanL2GatewayUtils.getSourceDpnTepIp(dpn.getDpId(),
+ new NodeId(l2GwDevice.getHwvtepNodeId()));
+ if (internalTunnelIp != null) {
+ tepIps.add(internalTunnelIp);
+ }
+ }
+ return tepIps;
+ }
+
+ /**
+ * Gets the all tep ips of l2 gw devices.
+ *
+ * @param devices
+ * the devices
+ * @return the all tep ips of l2 gw devices
+ */
+ private static List<IpAddress> getAllTepIpsOfL2GwDevices(ConcurrentMap<String, L2GatewayDevice> devices) {
+ List<IpAddress> tepIps = new ArrayList<>();
+ for (L2GatewayDevice otherDevice : devices.values()) {
+ tepIps.add(otherDevice.getTunnelIp());
+ }
+ return tepIps;
+ }
+
+ /**
+ * Handle mcast for elan l2 gw device delete.
+ *
+ * @param elanInstance
+ * the elan instance
+ * @param l2GatewayDevice
+ * the l2 gateway device
+ * @return the listenable future
+ */
+ public static List<ListenableFuture<Void>> handleMcastForElanL2GwDeviceDelete(ElanInstance elanInstance,
+ L2GatewayDevice l2GatewayDevice) {
+ ListenableFuture<Void> updateMcastMacsFuture = updateMcastMacsForAllElanDevices(elanInstance.getElanInstanceName(),
+ l2GatewayDevice, false/* updateThisDevice */);
+ ListenableFuture<Void> deleteRemoteMcastMacFuture = deleteRemoteMcastMac(
+ new NodeId(l2GatewayDevice.getHwvtepNodeId()), elanInstance.getElanInstanceName());
+ return Lists.newArrayList(updateMcastMacsFuture, deleteRemoteMcastMacFuture);
+ }
+
+ /**
+ * Delete remote mcast mac from Hwvtep node.
+ *
+ * @param nodeId
+ * the node id
+ * @param logicalSwitchName
+ * the logical switch name
+ * @return the listenable future
+ */
+ private static ListenableFuture<Void> deleteRemoteMcastMac(NodeId nodeId, String logicalSwitchName) {
+ InstanceIdentifier<LogicalSwitches> logicalSwitch = HwvtepSouthboundUtils
+ .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName));
+ RemoteMcastMacsKey remoteMcastMacsKey = new RemoteMcastMacsKey(new HwvtepLogicalSwitchRef(logicalSwitch),
+ new MacAddress(ElanConstants.UNKNOWN_DMAC));
+
+ RemoteMcastMacs remoteMcast = HwvtepUtils.getRemoteMcastMac(broker, LogicalDatastoreType.OPERATIONAL, nodeId,
+ remoteMcastMacsKey);
+ if (remoteMcast != null) {
+ LOG.info("Deleting RemoteMcastMacs entry on node: {} for logical switch: {}", nodeId.getValue(),
+ logicalSwitchName);
+ return HwvtepUtils.deleteRemoteMcastMac(broker, nodeId, remoteMcastMacsKey);
+ }
+
+ SettableFuture<Void> future = SettableFuture.create();
+ future.set(null);
+ return future;
+ }
+
+ /**
+ * Gets the tep ip of designated switch for external tunnel.
+ *
+ * @param l2GwDevice
+ * the l2 gw device
+ * @param elanInstanceName
+ * the elan instance name
+ * @return the tep ip of designated switch for external tunnel
+ */
+ public static IpAddress getTepIpOfDesignatedSwitchForExternalTunnel(L2GatewayDevice l2GwDevice,
+ String elanInstanceName) {
+ IpAddress tepIp = null;
+ DesignatedSwitchForTunnel desgSwitch = getDesignatedSwitchForExternalTunnel(l2GwDevice.getTunnelIp(),
+ elanInstanceName);
+ if (desgSwitch != null) {
+ tepIp = ElanL2GatewayUtils.getSourceDpnTepIp(BigInteger.valueOf(desgSwitch.getDpId()),
+ new NodeId(l2GwDevice.getHwvtepNodeId()));
+ }
+ return tepIp;
+ }
+
+ /**
+ * Gets the designated switch for external tunnel.
+ *
+ * @param tunnelIp
+ * the tunnel ip
+ * @param elanInstanceName
+ * the elan instance name
+ * @return the designated switch for external tunnel
+ */
+ public static DesignatedSwitchForTunnel getDesignatedSwitchForExternalTunnel(IpAddress tunnelIp,
+ String elanInstanceName) {
+ InstanceIdentifier<DesignatedSwitchForTunnel> instanceIdentifier = InstanceIdentifier
+ .builder(DesignatedSwitchesForExternalTunnels.class)
+ .child(DesignatedSwitchForTunnel.class, new DesignatedSwitchForTunnelKey(elanInstanceName, tunnelIp))
+ .build();
+ Optional<DesignatedSwitchForTunnel> designatedSwitchForTunnelOptional = MDSALUtil.read(broker,
+ LogicalDatastoreType.CONFIGURATION, instanceIdentifier);
+ if (designatedSwitchForTunnelOptional.isPresent()) {
+ return designatedSwitchForTunnelOptional.get();
+ }
+ 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.l2gw.utils;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+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.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.elanmanager.utils.ElanL2GwCacheUtils;
+import org.opendaylight.vpnservice.elan.l2gw.jobs.DeleteL2GwDeviceMacsFromElanJob;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.elan.l2gw.jobs.LogicalSwitchDeletedJob;
+import org.opendaylight.vpnservice.elan.l2gw.listeners.HwvtepPhysicalLocatorListener;
+import org.opendaylight.vpnservice.elan.utils.ElanClusterUtils;
+import org.opendaylight.vpnservice.elan.utils.ElanConstants;
+import org.opendaylight.vpnservice.elan.utils.ElanUtils;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.vpnservice.utils.SystemPropertyReader;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepSouthboundConstants;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepSouthboundUtils;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepUtils;
+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;
+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.yang.types.rev130715.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.neutron.l2gateways.rev150712.l2gateway.attributes.Devices;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindings;
+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.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
+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.instances.ElanInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.forwarding.entries.MacEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.AddL2GwDeviceInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * It gathers a set of utility methods that handle ELAN configuration in external Devices (where external means
+ * "not-CSS". As of now: TORs).
+ *
+ * It makes use of HwvtepUtils class located under ovsdb/hwvtepsouthbound project for low-level mdsal operations
+ *
+ * @author eperefr
+ *
+ */
+public class ElanL2GatewayUtils {
+ private static DataBroker broker;
+ private static ItmRpcService itmRpcService;
+ private static DataStoreJobCoordinator dataStoreJobCoordinator;
+ private static Timer LogicalSwitchDeleteJobTimer = new Timer();
+ private static final int LOGICAL_SWITCH_DELETE_DELAY = 120000;
+ private static ConcurrentMap<Pair<NodeId, String>, TimerTask> LogicalSwitchDeletedTasks =
+ new ConcurrentHashMap<Pair<NodeId, String>, TimerTask>();
+
+ private static final Logger LOG = LoggerFactory.getLogger(ElanL2GatewayUtils.class);
+
+ /**
+ * Sets the data broker.
+ *
+ * @param dataBroker
+ * the new data broker
+ */
+ public static void setDataBroker(DataBroker dataBroker) {
+ broker = dataBroker;
+ }
+
+ /**
+ * Sets the itm rpc service.
+ *
+ * @param itmRpc
+ * the new itm rpc service
+ */
+ public static void setItmRpcService(ItmRpcService itmRpc) {
+ itmRpcService = itmRpc;
+ }
+
+ /**
+ * Sets DataStoreJobCoordinator
+ *
+ * @param dsJobCoordinator
+ * the new dataStoreJobCoordinator
+ */
+ public static void setDataStoreJobCoordinator(DataStoreJobCoordinator dsJobCoordinator) {
+ dataStoreJobCoordinator = dsJobCoordinator;
+ }
+
+ /**
+ * Installs dpn macs in external device.
+ * first it checks if the physical locator towards this dpn tep is present or not
+ * if the physical locator is present go ahead and add the ucast macs
+ * otherwise update the mcast mac entry to include this dpn tep ip
+ * and schedule the job to put ucast macs once the physical locator is programmed in device
+ * @param elanName
+ * the elan name
+ * @param lstElanInterfaceNames
+ * the lst Elan interface names
+ * @param dpnId
+ * the dpn id
+ * @param externalNodeId
+ * the external node id
+ */
+ public static void installDpnMacsInL2gwDevice(String elanName, Set<String> lstElanInterfaceNames,
+ BigInteger dpnId, NodeId externalNodeId) {
+ L2GatewayDevice elanL2GwDevice = ElanL2GwCacheUtils.getL2GatewayDeviceFromCache(elanName,
+ externalNodeId.getValue());
+ if (elanL2GwDevice == null) {
+ LOG.debug("L2 gw device not found in elan cache for device name {}", externalNodeId);
+ return;
+ }
+ IpAddress dpnTepIp = getSourceDpnTepIp(dpnId, externalNodeId);
+ if (dpnTepIp == null) {
+ LOG.warn("Could not install dpn macs in l2gw device , dpnTepIp not found dpn : {} , nodeid : {}",
+ dpnId, externalNodeId);
+ return;
+ }
+
+ String logicalSwitchName = getLogicalSwitchFromElan(elanName);
+ RemoteMcastMacs remoteMcastMac = readRemoteMcastMac(externalNodeId, logicalSwitchName,
+ LogicalDatastoreType.OPERATIONAL);
+ boolean phyLocAlreadyExists = checkIfPhyLocatorAlreadyExistsInRemoteMcastEntry(externalNodeId, remoteMcastMac,
+ dpnTepIp);
+ LOG.debug("phyLocAlreadyExists = {} for locator [{}] in remote mcast entry for elan [{}], nodeId [{}]",
+ phyLocAlreadyExists, String.valueOf(dpnTepIp.getValue()), elanName, externalNodeId.getValue());
+ List<PhysAddress> staticMacs = null;
+ staticMacs = getElanDpnMacsFromInterfaces(lstElanInterfaceNames);
+
+ if (phyLocAlreadyExists) {
+ scheduleAddDpnMacsInExtDevice(elanName, dpnId, staticMacs, elanL2GwDevice);
+ return;
+ }
+ ElanL2GatewayMulticastUtils.scheduleMcastMacUpdateJob(elanName, elanL2GwDevice);
+ scheduleAddDpnMacsInExtDevice(elanName, dpnId, staticMacs, elanL2GwDevice);
+ }
+
+ /**
+ * gets the macs addresses for elan interfaces
+ *
+ * @param lstElanInterfaceNames
+ * the lst elan interface names
+ * @return the list
+ */
+ private static List<PhysAddress> getElanDpnMacsFromInterfaces(Set<String> lstElanInterfaceNames) {
+ List<PhysAddress> result = new ArrayList<>();
+ for (String interfaceName : lstElanInterfaceNames) {
+ ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
+ if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
+ for (MacEntry macEntry : elanInterfaceMac.getMacEntry()) {
+ result.add(macEntry.getMacAddress());
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Check if phy locator already exists in remote mcast entry.
+ *
+ * @param nodeId
+ * the node id
+ * @param remoteMcastMac
+ * the remote mcast mac
+ * @param expectedPhyLocatorIp
+ * the expected phy locator ip
+ * @return true, if successful
+ */
+ public static boolean checkIfPhyLocatorAlreadyExistsInRemoteMcastEntry(NodeId nodeId,
+ RemoteMcastMacs remoteMcastMac, IpAddress expectedPhyLocatorIp) {
+ if (remoteMcastMac != null) {
+ HwvtepPhysicalLocatorAugmentation expectedPhyLocatorAug = HwvtepSouthboundUtils
+ .createHwvtepPhysicalLocatorAugmentation(String.valueOf(expectedPhyLocatorIp.getValue()));
+ HwvtepPhysicalLocatorRef expectedPhyLocRef = new HwvtepPhysicalLocatorRef(
+ HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(nodeId, expectedPhyLocatorAug));
+ if (remoteMcastMac.getLocatorSet() != null) {
+ for (LocatorSet locatorSet : remoteMcastMac.getLocatorSet()) {
+ if (locatorSet.getLocatorRef().equals(expectedPhyLocRef)) {
+ LOG.trace("matched phyLocRef: {}", expectedPhyLocRef);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Gets the remote mcast mac.
+ *
+ * @param nodeId
+ * the node id
+ * @param logicalSwitchName
+ * the logical switch name
+ * @param datastoreType
+ * the datastore type
+ * @return the remote mcast mac
+ */
+ public static RemoteMcastMacs readRemoteMcastMac(NodeId nodeId, String logicalSwitchName,
+ LogicalDatastoreType datastoreType) {
+ InstanceIdentifier<LogicalSwitches> logicalSwitch = HwvtepSouthboundUtils
+ .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName));
+ RemoteMcastMacsKey remoteMcastMacsKey = new RemoteMcastMacsKey(new HwvtepLogicalSwitchRef(logicalSwitch),
+ new MacAddress(ElanConstants.UNKNOWN_DMAC));
+ RemoteMcastMacs remoteMcastMac = HwvtepUtils.getRemoteMcastMac(broker, datastoreType, nodeId,
+ remoteMcastMacsKey);
+ return remoteMcastMac;
+ }
+
+ /**
+ * Removes the given MAC Addresses from all the External Devices belonging
+ * to the specified ELAN.
+ *
+ * @param elanInstance
+ * the elan instance
+ * @param macAddresses
+ * the mac addresses
+ */
+ public static void removeMacsFromElanExternalDevices(ElanInstance elanInstance, List<PhysAddress> macAddresses) {
+ ConcurrentMap<String, L2GatewayDevice> elanL2GwDevices = ElanL2GwCacheUtils
+ .getInvolvedL2GwDevices(elanInstance.getElanInstanceName());
+ for (L2GatewayDevice l2GatewayDevice : elanL2GwDevices.values()) {
+ removeRemoteUcastMacsFromExternalDevice(l2GatewayDevice.getHwvtepNodeId(),
+ elanInstance.getElanInstanceName(), macAddresses);
+ }
+ }
+
+ /**
+ * Removes the given MAC Addresses from the specified External Device.
+ *
+ * @param deviceNodeId
+ * the device node id
+ * @param logicalSwitchName
+ * @param macAddresses
+ * the mac addresses
+ * @return the listenable future
+ */
+ private static ListenableFuture<Void> removeRemoteUcastMacsFromExternalDevice(String deviceNodeId,
+ String logicalSwitchName, List<PhysAddress> macAddresses) {
+ NodeId nodeId = new NodeId(deviceNodeId);
+
+ // TODO (eperefr)
+ List<MacAddress> lstMac = Lists.transform(macAddresses, new Function<PhysAddress, MacAddress>() {
+ @Override
+ public MacAddress apply(PhysAddress physAddress) {
+ return (physAddress != null) ? new MacAddress(physAddress.getValue()) : null;
+ }
+ });
+ return HwvtepUtils.deleteRemoteUcastMacs(broker, nodeId, logicalSwitchName, lstMac);
+ }
+
+ public static ElanInstance getElanInstanceForUcastLocalMac(LocalUcastMacs localUcastMac) {
+ Optional<LogicalSwitches> lsOpc = ElanUtils.read(broker, LogicalDatastoreType.OPERATIONAL,
+ (InstanceIdentifier<LogicalSwitches>) localUcastMac.getLogicalSwitchRef().getValue());
+ if (lsOpc.isPresent()) {
+ LogicalSwitches ls = lsOpc.get();
+ if (ls != null) {
+ // Logical switch name is Elan name
+ String elanName = getElanFromLogicalSwitch(ls.getHwvtepNodeName().getValue());
+ return ElanUtils.getElanInstanceByName(elanName);
+ } else {
+ String macAddress = localUcastMac.getMacEntryKey().getValue();
+ LOG.error("Could not find logical_switch for {} being added/deleted", macAddress);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Install external device local macs in dpn.
+ *
+ * @param dpnId
+ * the dpn id
+ * @param l2gwDeviceNodeId
+ * the l2gw device node id
+ * @param elan
+ * the elan
+ */
+ public static void installL2gwDeviceMacsInDpn(BigInteger dpnId, NodeId l2gwDeviceNodeId, ElanInstance elan) {
+ L2GatewayDevice l2gwDevice = ElanL2GwCacheUtils.getL2GatewayDeviceFromCache(elan.getElanInstanceName(),
+ l2gwDeviceNodeId.getValue());
+ if (l2gwDevice == null) {
+ LOG.debug("L2 gw device not found in elan cache for device name {}", l2gwDeviceNodeId.getValue());
+ return;
+ }
+
+ installDmacFlowsOnDpn(dpnId, l2gwDevice, elan);
+ }
+
+ /**
+ * Install dmac flows on dpn.
+ *
+ * @param dpnId
+ * the dpn id
+ * @param l2gwDevice
+ * the l2gw device
+ * @param elan
+ * the elan
+ */
+ public static void installDmacFlowsOnDpn(BigInteger dpnId, L2GatewayDevice l2gwDevice, ElanInstance elan) {
+ String elanName = elan.getElanInstanceName();
+
+ List<LocalUcastMacs> l2gwDeviceLocalMacs = l2gwDevice.getUcastLocalMacs();
+ if (l2gwDeviceLocalMacs != null && !l2gwDeviceLocalMacs.isEmpty()) {
+ for (LocalUcastMacs localUcastMac : l2gwDeviceLocalMacs) {
+ //TODO batch these ops
+ ElanUtils.installDmacFlowsToExternalRemoteMac(dpnId, l2gwDevice.getHwvtepNodeId(), elan.getElanTag(),
+ elan.getVni(), localUcastMac.getMacEntryKey().getValue(), elanName);
+ }
+ LOG.debug("Installing L2gw device [{}] local macs [size: {}] in dpn [{}] for elan [{}]",
+ l2gwDevice.getHwvtepNodeId(), l2gwDeviceLocalMacs.size(), dpnId, elanName);
+ }
+ }
+
+ /**
+ * Install elan l2gw devices local macs in dpn.
+ *
+ * @param dpnId
+ * the dpn id
+ * @param elan
+ * the elan
+ */
+ public static void installElanL2gwDevicesLocalMacsInDpn(BigInteger dpnId, ElanInstance elan) {
+ ConcurrentMap<String, L2GatewayDevice> elanL2GwDevicesFromCache = ElanL2GwCacheUtils
+ .getInvolvedL2GwDevices(elan.getElanInstanceName());
+ if (elanL2GwDevicesFromCache != null) {
+ for (L2GatewayDevice l2gwDevice : elanL2GwDevicesFromCache.values()) {
+ installDmacFlowsOnDpn(dpnId, l2gwDevice, elan);
+ }
+ } else {
+ LOG.debug("No Elan l2 gateway devices in cache for [{}] ", elan.getElanInstanceName());
+ }
+ }
+
+ public static void installL2GwUcastMacInElan(final ElanInstance elan,
+ final L2GatewayDevice extL2GwDevice, final String macToBeAdded) {
+ final String extDeviceNodeId = extL2GwDevice.getHwvtepNodeId();
+ final String elanInstanceName = elan.getElanInstanceName();
+
+ // Retrieve all participating DPNs in this Elan. Populate this MAC in DMAC table.
+ // Looping through all DPNs in order to add/remove mac flows in their DMAC table
+ final List<DpnInterfaces> elanDpns = ElanUtils.getInvolvedDpnsInElan(elanInstanceName);
+ if (elanDpns != null && elanDpns.size() > 0) {
+ String jobKey = elan.getElanInstanceName() + ":" + macToBeAdded;
+ ElanClusterUtils.runOnlyInLeaderNode(jobKey,
+ "install l2gw mcas in dmac table",
+ new Callable<List<ListenableFuture<Void>>>() {
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ List<ListenableFuture<Void>> fts = Lists.newArrayList();
+ for (DpnInterfaces elanDpn : elanDpns) {
+ //TODO batch the below call
+ fts.addAll(ElanUtils.installDmacFlowsToExternalRemoteMac(elanDpn.getDpId(),
+ extDeviceNodeId, elan.getElanTag(), elan.getVni(), macToBeAdded,
+ elanInstanceName));
+ }
+ return fts;
+ }
+ });
+ }
+ final IpAddress extL2GwDeviceTepIp = extL2GwDevice.getTunnelIp();
+ final List<PhysAddress> macList = new ArrayList<PhysAddress>();
+ macList.add(new PhysAddress(macToBeAdded));
+
+ String jobKey = "hwvtep:"+elan.getElanInstanceName() + ":" + macToBeAdded;
+ ElanClusterUtils.runOnlyInLeaderNode(jobKey,
+ "install remote ucast macs in l2gw device",
+ new Callable<List<ListenableFuture<Void>>>() {
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ ConcurrentMap<String, L2GatewayDevice> elanL2GwDevices =
+ ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanInstanceName);
+
+ List<ListenableFuture<Void>> fts = Lists.newArrayList();
+ for (L2GatewayDevice otherDevice : elanL2GwDevices.values()) {
+ if (!otherDevice.getHwvtepNodeId().equals(extDeviceNodeId)
+ && !areMLAGDevices(extL2GwDevice, otherDevice)) {
+ final String hwvtepId = otherDevice.getHwvtepNodeId();
+ InstanceIdentifier<Node> iid = HwvtepSouthboundUtils.createInstanceIdentifier(
+ new NodeId(hwvtepId));
+ final String logicalSwitchName = elanInstanceName;
+
+ ListenableFuture<Void> ft = HwvtepUtils.installUcastMacs(
+ broker, hwvtepId, macList, logicalSwitchName, extL2GwDeviceTepIp);
+ //TODO batch the above call
+ Futures.addCallback(ft, new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(Void noarg) {
+ LOG.trace("Successful in initiating ucast_remote_macs addition" +
+ "related to {} in {}", logicalSwitchName, hwvtepId);
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ LOG.error(String.format("Failed adding ucast_remote_macs related to " +
+ "%s in %s", logicalSwitchName, hwvtepId), error);
+ };
+ });
+ fts.add(ft);
+ }
+ }
+ return fts;
+ }});
+ }
+
+ /**
+ * Un install l2 gw ucast mac from elan.
+ *
+ * @param elan
+ * the elan
+ * @param l2GwDevice
+ * the l2 gw device
+ * @param macAddresses
+ * the mac addresses
+ */
+ public static void unInstallL2GwUcastMacFromElan(final ElanInstance elan, final L2GatewayDevice l2GwDevice,
+ final List<MacAddress> macAddresses) {
+ if (macAddresses == null || macAddresses.isEmpty()) {
+ return;
+ }
+ final String elanName = elan.getElanInstanceName();
+
+ // Retrieve all participating DPNs in this Elan. Populate this MAC in
+ // DMAC table. Looping through all DPNs in order to add/remove mac flows
+ // in their DMAC table
+ for (final MacAddress mac : macAddresses) {
+ final List<DpnInterfaces> elanDpns = ElanUtils.getInvolvedDpnsInElan(elanName);
+ if (elanDpns != null && !elanDpns.isEmpty()) {
+ String jobKey = elanName + ":" + mac.getValue();
+ ElanClusterUtils.runOnlyInLeaderNode(jobKey, "delete l2gw macs from dmac table",
+ new Callable<List<ListenableFuture<Void>>>() {
+ @Override
+ public List<ListenableFuture<Void>> call() {
+ List<ListenableFuture<Void>> fts = Lists.newArrayList();
+ for (DpnInterfaces elanDpn : elanDpns) {
+ BigInteger dpnId = elanDpn.getDpId();
+ // never batch deletes
+ fts.addAll(ElanUtils.deleteDmacFlowsToExternalMac(elan.getElanTag(), dpnId,
+ l2GwDevice.getHwvtepNodeId(), mac.getValue()));
+ }
+ return fts;
+ }
+ });
+ }
+ }
+
+ DeleteL2GwDeviceMacsFromElanJob job = new DeleteL2GwDeviceMacsFromElanJob(broker, elanName, l2GwDevice,
+ macAddresses);
+ ElanClusterUtils.runOnlyInLeaderNode(job.getJobKey(), "delete remote ucast macs in l2gw devices", job);
+ }
+
+ /**
+ * Delete elan l2 gateway devices ucast local macs from dpn.
+ *
+ * @param elanName
+ * the elan name
+ * @param dpnId
+ * the dpn id
+ */
+ public static void deleteElanL2GwDevicesUcastLocalMacsFromDpn(final String elanName, final BigInteger dpnId) {
+ ConcurrentMap<String, L2GatewayDevice> elanL2GwDevices = ElanL2GwCacheUtils.getInvolvedL2GwDevices(elanName);
+ if (elanL2GwDevices == null || elanL2GwDevices.isEmpty()) {
+ LOG.trace("No L2 gateway devices in Elan [{}] cache.", elanName);
+ return;
+ }
+ final ElanInstance elan = ElanUtils.getElanInstanceByName(elanName);
+ if (elan == null) {
+ LOG.error("Could not find Elan by name: {}", elanName);
+ return;
+ }
+ LOG.info("Deleting Elan [{}] L2GatewayDevices UcastLocalMacs from Dpn [{}]", elanName, dpnId);
+
+ final Long elanTag = elan.getElanTag();
+ for (final L2GatewayDevice l2GwDevice : elanL2GwDevices.values()) {
+ List<MacAddress> localMacs = getL2GwDeviceLocalMacs(l2GwDevice);
+ if (localMacs != null && !localMacs.isEmpty()) {
+ for (final MacAddress mac : localMacs) {
+ String jobKey = elanName + ":" + mac.getValue();
+ ElanClusterUtils.runOnlyInLeaderNode(jobKey, "delete l2gw macs from dmac table",
+ new Callable<List<ListenableFuture<Void>>>() {
+ @Override
+ public List<ListenableFuture<Void>> call() {
+ List<ListenableFuture<Void>> futures = Lists.newArrayList();
+
+ futures.addAll(ElanUtils.deleteDmacFlowsToExternalMac(elanTag, dpnId,
+ l2GwDevice.getHwvtepNodeId(), mac.getValue()));
+ return futures;
+ }
+ });
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the l2 gw device local macs.
+ *
+ * @param l2gwDevice
+ * the l2gw device
+ * @return the l2 gw device local macs
+ */
+ public static List<MacAddress> getL2GwDeviceLocalMacs(L2GatewayDevice l2gwDevice) {
+ List<MacAddress> macs = new ArrayList<>();
+ if (l2gwDevice == null) {
+ return macs;
+ }
+ List<LocalUcastMacs> lstUcastLocalMacs = l2gwDevice.getUcastLocalMacs();
+ if (lstUcastLocalMacs != null && !lstUcastLocalMacs.isEmpty()) {
+ macs = Lists.transform(lstUcastLocalMacs, new Function<LocalUcastMacs, MacAddress>() {
+ @Override
+ public MacAddress apply(LocalUcastMacs localUcastMac) {
+ return (localUcastMac != null) ? localUcastMac.getMacEntryKey() : null;
+ }
+ });
+ }
+ return macs;
+ }
+
+ /**
+ * Delete elan macs from L2 gateway device.<br>
+ * This includes deleting ELAN mac table entries plus external device
+ * UcastLocalMacs which are part of the same ELAN.
+ *
+ * @param l2GatewayDevice
+ * the l2 gateway device
+ * @param elanName
+ * the elan name
+ * @return the listenable future
+ */
+ public static ListenableFuture<Void> deleteElanMacsFromL2GatewayDevice(L2GatewayDevice l2GatewayDevice,
+ String elanName) {
+ List<MacAddress> elanMacTableEntries = getElanMacTableEntries(elanName);
+ List<MacAddress> elanL2GatewayDevicesLocalMacs = getElanL2GatewayDevicesLocalMacs(l2GatewayDevice, elanName);
+
+ List<MacAddress> lstElanLocalMacs = new ArrayList<>(elanMacTableEntries);
+ lstElanLocalMacs.addAll(elanL2GatewayDevicesLocalMacs);
+
+ return HwvtepUtils.deleteRemoteUcastMacs(broker, new NodeId(l2GatewayDevice.getHwvtepNodeId()),
+ elanName, lstElanLocalMacs);
+ }
+
+ /**
+ * Gets the elan mac table entries.
+ *
+ * @param elanName
+ * the elan name
+ * @return the elan mac table entries as list
+ */
+ public static List<MacAddress> getElanMacTableEntries(String elanName) {
+ MacTable macTable = ElanUtils.getElanMacTable(elanName);
+ if (macTable == null || macTable.getMacEntry() == null || macTable.getMacEntry().isEmpty()) {
+ LOG.trace("MacTable is empty for elan: {}", elanName);
+ return Collections.emptyList();
+ }
+ List<MacAddress> lstMacs = Lists.transform(macTable.getMacEntry(), new Function<MacEntry, MacAddress>() {
+ @Override
+ public MacAddress apply(MacEntry macEntry) {
+ return (macEntry != null) ? new MacAddress(macEntry.getMacAddress().getValue()) : null;
+ }
+ });
+ return lstMacs;
+ }
+
+ /**
+ * Gets the elan l2 gateway devices local macs.
+ *
+ * @param l2GwDeviceToBeExcluded
+ * the l2 gw device to be excluded
+ * @param elanName
+ * the elan name
+ * @return the elan l2 gateway devices local macs
+ */
+ public static List<MacAddress> getElanL2GatewayDevicesLocalMacs(L2GatewayDevice l2GwDeviceToBeExcluded,
+ String elanName) {
+ List<MacAddress> lstL2GatewayDeviceMacs = new ArrayList<>();
+
+ ConcurrentMap<String, L2GatewayDevice> elanL2GwDevicesFromCache = ElanL2GwCacheUtils
+ .getInvolvedL2GwDevices(elanName);
+ if (elanL2GwDevicesFromCache != null) {
+ for (L2GatewayDevice otherDevice : elanL2GwDevicesFromCache.values()) {
+ if (!otherDevice.getHwvtepNodeId().equals(l2GwDeviceToBeExcluded.getHwvtepNodeId())) {
+ List<LocalUcastMacs> lstUcastLocalMacs = otherDevice.getUcastLocalMacs();
+ if (lstUcastLocalMacs != null) {
+ List<MacAddress> l2GwDeviceMacs = Lists.transform(lstUcastLocalMacs,
+ new Function<LocalUcastMacs, MacAddress>() {
+ @Override
+ public MacAddress apply(LocalUcastMacs localUcastMac) {
+ return (localUcastMac != null) ? localUcastMac.getMacEntryKey() : null;
+ }
+ });
+ lstL2GatewayDeviceMacs.addAll(l2GwDeviceMacs);
+ }
+ }
+ }
+ }
+ return lstL2GatewayDeviceMacs;
+ }
+
+ /**
+ * Install ELAN macs in L2 Gateway device.<br>
+ * This includes installing ELAN mac table entries plus external device
+ * UcastLocalMacs which are part of the same ELAN.
+ *
+ * @param elanName
+ * the elan name
+ * @param l2GatewayDevice
+ * the l2 gateway device which has to be configured
+ * @return the listenable future
+ */
+ public static ListenableFuture<Void> installElanMacsInL2GatewayDevice(String elanName,
+ L2GatewayDevice l2GatewayDevice) {
+ String logicalSwitchName = getLogicalSwitchFromElan(elanName);
+ NodeId hwVtepNodeId = new NodeId(l2GatewayDevice.getHwvtepNodeId());
+
+ List<RemoteUcastMacs> lstL2GatewayDevicesMacs = getOtherDevicesMacs(elanName,
+ l2GatewayDevice, hwVtepNodeId, logicalSwitchName);
+ List<RemoteUcastMacs> lstElanMacTableEntries = getElanMacTableEntriesMacs(elanName,
+ l2GatewayDevice, hwVtepNodeId, logicalSwitchName);
+
+ List<RemoteUcastMacs> lstRemoteUcastMacs = new ArrayList<>(lstL2GatewayDevicesMacs);
+ lstRemoteUcastMacs.addAll(lstElanMacTableEntries);
+
+ ListenableFuture<Void> future = HwvtepUtils.addRemoteUcastMacs(broker, hwVtepNodeId, lstRemoteUcastMacs);
+
+ LOG.info("Added RemoteUcastMacs entries [{}] in config DS. NodeID: {}, LogicalSwitch: {}",
+ lstRemoteUcastMacs.size(), hwVtepNodeId.getValue(), logicalSwitchName);
+ return future;
+ }
+
+ /**
+ * Gets the l2 gateway devices ucast local macs as remote ucast macs.
+ *
+ * @param elanName
+ * the elan name
+ * @param l2GatewayDeviceToBeConfigured
+ * the l2 gateway device to be configured
+ * @param hwVtepNodeId
+ * the hw vtep node Id to be configured
+ * @param logicalSwitchName
+ * the logical switch name
+ * @return the l2 gateway devices macs as remote ucast macs
+ */
+ public static List<RemoteUcastMacs> getOtherDevicesMacs(String elanName,
+ L2GatewayDevice l2GatewayDeviceToBeConfigured,
+ NodeId hwVtepNodeId, String logicalSwitchName) {
+ List<RemoteUcastMacs> lstRemoteUcastMacs = new ArrayList<RemoteUcastMacs>();
+ ConcurrentMap<String, L2GatewayDevice> elanL2GwDevicesFromCache = ElanL2GwCacheUtils
+ .getInvolvedL2GwDevices(elanName);
+
+ if (elanL2GwDevicesFromCache != null) {
+ for (L2GatewayDevice otherDevice : elanL2GwDevicesFromCache.values()) {
+ if (l2GatewayDeviceToBeConfigured.getHwvtepNodeId().equals(otherDevice.getHwvtepNodeId())) {
+ continue;
+ }
+ if (!areMLAGDevices(l2GatewayDeviceToBeConfigured, otherDevice)) {
+ List<LocalUcastMacs> lstUcastLocalMacs = otherDevice.getUcastLocalMacs();
+ if (lstUcastLocalMacs != null) {
+ for (LocalUcastMacs localUcastMac : lstUcastLocalMacs) {
+ HwvtepPhysicalLocatorAugmentation physLocatorAug = HwvtepSouthboundUtils
+ .createHwvtepPhysicalLocatorAugmentation(
+ String.valueOf(otherDevice.getTunnelIp().getValue()));
+ RemoteUcastMacs remoteUcastMac = HwvtepSouthboundUtils.createRemoteUcastMac(hwVtepNodeId,
+ localUcastMac.getMacEntryKey().getValue(), localUcastMac.getIpaddr(),
+ logicalSwitchName, physLocatorAug);
+ lstRemoteUcastMacs.add(remoteUcastMac);
+ }
+ }
+ }
+ }
+ }
+ return lstRemoteUcastMacs;
+ }
+
+ /**
+ * Are MLAG devices.
+ *
+ * @param l2GatewayDevice
+ * the l2 gateway device
+ * @param otherL2GatewayDevice
+ * the other l2 gateway device
+ * @return true, if both the specified l2 gateway devices are part of same
+ * MLAG
+ */
+ public static boolean areMLAGDevices(L2GatewayDevice l2GatewayDevice, L2GatewayDevice otherL2GatewayDevice) {
+ // If tunnel IPs are same, then it is considered to be part of same MLAG
+ return Objects.equals(l2GatewayDevice.getTunnelIp(), otherL2GatewayDevice.getTunnelIp());
+ }
+
+ /**
+ * Gets the elan mac table entries as remote ucast macs. <br>
+ * Note: ELAN MAC table only contains internal switches MAC's. It doesn't
+ * contain external device MAC's.
+ *
+ * @param elanName
+ * the elan name
+ * @param l2GatewayDeviceToBeConfigured
+ * the l2 gateway device to be configured
+ * @param hwVtepNodeId
+ * the hw vtep node id
+ * @param logicalSwitchName
+ * the logical switch name
+ * @return the elan mac table entries as remote ucast macs
+ */
+ public static List<RemoteUcastMacs> getElanMacTableEntriesMacs(String elanName,
+ L2GatewayDevice l2GatewayDeviceToBeConfigured,
+ NodeId hwVtepNodeId, String logicalSwitchName) {
+ List<RemoteUcastMacs> lstRemoteUcastMacs = new ArrayList<RemoteUcastMacs>();
+
+ MacTable macTable = ElanUtils.getElanMacTable(elanName);
+ if (macTable == null || macTable.getMacEntry() == null || macTable.getMacEntry().isEmpty()) {
+ LOG.trace("MacTable is empty for elan: {}", elanName);
+ return lstRemoteUcastMacs;
+ }
+
+ for (MacEntry macEntry : macTable.getMacEntry()) {
+ BigInteger dpnId = ElanUtils.getDpidFromInterface(macEntry.getInterface());
+ if (dpnId == null) {
+ LOG.error("DPN ID not found for interface {}", macEntry.getInterface());
+ continue;
+ }
+
+ IpAddress dpnTepIp = getSourceDpnTepIp(dpnId, hwVtepNodeId);
+ LOG.trace("Dpn Tep IP: {} for dpnId: {} and nodeId: {}", dpnTepIp, dpnId, hwVtepNodeId.getValue());
+ if (dpnTepIp == null) {
+ LOG.error("TEP IP not found for dpnId {} and nodeId {}", dpnId, hwVtepNodeId.getValue());
+ continue;
+ }
+ HwvtepPhysicalLocatorAugmentation physLocatorAug = HwvtepSouthboundUtils
+ .createHwvtepPhysicalLocatorAugmentation(String.valueOf(dpnTepIp.getValue()));
+ // TODO: Query ARP cache to get IP address corresponding to the
+ // MAC
+ IpAddress ipAddress = null;
+ RemoteUcastMacs remoteUcastMac = HwvtepSouthboundUtils.createRemoteUcastMac(hwVtepNodeId,
+ macEntry.getMacAddress().getValue(), ipAddress, logicalSwitchName, physLocatorAug);
+ lstRemoteUcastMacs.add(remoteUcastMac);
+ }
+ return lstRemoteUcastMacs;
+ }
+
+ /**
+ * Gets the external tunnel interface name.
+ *
+ * @param sourceNode
+ * the source node
+ * @param dstNode
+ * the dst node
+ * @return the external tunnel interface name
+ */
+ public static String getExternalTunnelInterfaceName(String sourceNode, String dstNode) {
+ Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
+ String tunnelInterfaceName = null;
+ try {
+ Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> output = itmRpcService
+ .getExternalTunnelInterfaceName(new GetExternalTunnelInterfaceNameInputBuilder()
+ .setSourceNode(sourceNode).setDestinationNode(dstNode).setTunnelType(tunType).build());
+
+ RpcResult<GetExternalTunnelInterfaceNameOutput> rpcResult = output.get();
+ if (rpcResult.isSuccessful()) {
+ tunnelInterfaceName = rpcResult.getResult().getInterfaceName();
+ LOG.debug("Tunnel interface name: {} for sourceNode: {} and dstNode: {}", tunnelInterfaceName,
+ sourceNode, dstNode);
+ } else {
+ LOG.warn("RPC call to ITM.GetExternalTunnelInterfaceName failed with error: {}",
+ rpcResult.getErrors());
+ }
+ } catch (NullPointerException | InterruptedException | ExecutionException e) {
+ LOG.error("Failed to get external tunnel interface name for sourceNode: {} and dstNode: {}: {} ",
+ sourceNode, dstNode, e);
+ }
+ return tunnelInterfaceName;
+ }
+
+ /**
+ * Gets the source dpn tep ip.
+ *
+ * @param srcDpnId
+ * the src dpn id
+ * @param dstHwVtepNodeId
+ * the dst hw vtep node id
+ * @return the dpn tep ip
+ */
+ public static IpAddress getSourceDpnTepIp(BigInteger srcDpnId, NodeId dstHwVtepNodeId) {
+ IpAddress dpnTepIp = null;
+ String tunnelInterfaceName = getExternalTunnelInterfaceName(String.valueOf(srcDpnId),
+ dstHwVtepNodeId.getValue());
+ if (tunnelInterfaceName != null) {
+ Interface tunnelInterface = getInterfaceFromConfigDS(new InterfaceKey(tunnelInterfaceName), broker);
+ if (tunnelInterface != null) {
+ dpnTepIp = tunnelInterface.getAugmentation(IfTunnel.class).getTunnelSource();
+ } else {
+ LOG.warn("Tunnel interface not found for tunnelInterfaceName {}", tunnelInterfaceName);
+ }
+ } else {
+ LOG.warn("Tunnel interface name not found for srcDpnId {} and dstHwVtepNodeId {}", srcDpnId,
+ dstHwVtepNodeId);
+ }
+ return dpnTepIp;
+ }
+
+ /**
+ * Update vlan bindings in l2 gateway device.
+ *
+ * @param nodeId
+ * the node id
+ * @param logicalSwitchName
+ * the logical switch name
+ * @param hwVtepDevice
+ * the hardware device
+ * @param defaultVlanId
+ * the default vlan id
+ * @return the listenable future
+ */
+ public static ListenableFuture<Void> updateVlanBindingsInL2GatewayDevice(NodeId nodeId, String logicalSwitchName,
+ Devices hwVtepDevice, Integer defaultVlanId) {
+ if (hwVtepDevice == null || hwVtepDevice.getInterfaces() == null || hwVtepDevice.getInterfaces().isEmpty()) {
+ String errMsg = "HwVtepDevice is null or interfaces are empty.";
+ LOG.error(errMsg);
+ return Futures.immediateFailedFuture(new RuntimeException(errMsg));
+ }
+
+ WriteTransaction transaction = broker.newWriteOnlyTransaction();
+ for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.devices.Interfaces deviceInterface : hwVtepDevice
+ .getInterfaces()) {
+ List<VlanBindings> vlanBindings = new ArrayList<>();
+ if (deviceInterface.getSegmentationIds() != null && !deviceInterface.getSegmentationIds().isEmpty()) {
+ for (Integer vlanId : deviceInterface.getSegmentationIds()) {
+ vlanBindings.add(HwvtepSouthboundUtils.createVlanBinding(nodeId, vlanId, logicalSwitchName));
+ }
+ } else {
+ // Use defaultVlanId (specified in L2GatewayConnection) if Vlan
+ // ID not specified at interface level.
+ vlanBindings.add(HwvtepSouthboundUtils.createVlanBinding(nodeId, defaultVlanId, logicalSwitchName));
+ }
+ HwvtepUtils.mergeVlanBindings(transaction, nodeId, hwVtepDevice.getDeviceName(),
+ deviceInterface.getInterfaceName(), vlanBindings);
+ }
+ ListenableFuture<Void> future = transaction.submit();
+ LOG.info("Updated Hwvtep VlanBindings in config DS. NodeID: {}, LogicalSwitch: {}", nodeId.getValue(),
+ logicalSwitchName);
+ return future;
+ }
+
+ /**
+ * Delete vlan bindings from l2 gateway device.
+ *
+ * @param nodeId
+ * the node id
+ * @param hwVtepDevice
+ * the hw vtep device
+ * @param defaultVlanId
+ * the default vlan id
+ * @return the listenable future
+ */
+ public static ListenableFuture<Void> deleteVlanBindingsFromL2GatewayDevice(NodeId nodeId, Devices hwVtepDevice,
+ Integer defaultVlanId) {
+ if (hwVtepDevice == null || hwVtepDevice.getInterfaces() == null || hwVtepDevice.getInterfaces().isEmpty()) {
+ String errMsg = "HwVtepDevice is null or interfaces are empty.";
+ LOG.error(errMsg);
+ return Futures.immediateFailedFuture(new RuntimeException(errMsg));
+ }
+ NodeId physicalSwitchNodeId = HwvtepSouthboundUtils.createManagedNodeId(nodeId, hwVtepDevice.getDeviceName());
+
+ WriteTransaction transaction = broker.newWriteOnlyTransaction();
+ for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.devices.Interfaces deviceInterface : hwVtepDevice
+ .getInterfaces()) {
+ String phyPortName = deviceInterface.getInterfaceName();
+ if (deviceInterface.getSegmentationIds() != null && !deviceInterface.getSegmentationIds().isEmpty()) {
+ for (Integer vlanId : deviceInterface.getSegmentationIds()) {
+ HwvtepUtils.deleteVlanBinding(transaction, physicalSwitchNodeId, phyPortName, vlanId);
+ }
+ } else {
+ // Use defaultVlanId (specified in L2GatewayConnection) if Vlan
+ // ID not specified at interface level.
+ HwvtepUtils.deleteVlanBinding(transaction, physicalSwitchNodeId, phyPortName, defaultVlanId);
+ }
+ }
+ ListenableFuture<Void> future = transaction.submit();
+
+ LOG.info("Deleted Hwvtep VlanBindings from config DS. NodeID: {}, hwVtepDevice: {}, defaultVlanId: {} ",
+ nodeId.getValue(), hwVtepDevice, defaultVlanId);
+ return future;
+ }
+
+ /**
+ * Gets the elan name from logical switch name.
+ *
+ * @param logicalSwitchName
+ * the logical switch name
+ * @return the elan name from logical switch name
+ */
+ public static String getElanFromLogicalSwitch(String logicalSwitchName) {
+ // Assuming elan name is same as logical switch name
+ String elanName = logicalSwitchName;
+ return elanName;
+ }
+
+ /**
+ * Gets the logical switch name from elan name.
+ *
+ * @param elanName
+ * the elan name
+ * @return the logical switch from elan name
+ */
+ public static String getLogicalSwitchFromElan(String elanName) {
+ // Assuming logical switch name is same as elan name
+ String logicalSwitchName = elanName;
+ return logicalSwitchName;
+ }
+
+ /**
+ * Gets the l2 gateway connection job key.
+ *
+ * @param nodeId
+ * the node id
+ * @param logicalSwitchName
+ * the logical switch name
+ * @return the l2 gateway connection job key
+ */
+ public static String getL2GatewayConnectionJobKey(String nodeId, String logicalSwitchName) {
+ return logicalSwitchName;
+ }
+
+ public static InstanceIdentifier<Interface> getInterfaceIdentifier(InterfaceKey interfaceKey) {
+ InstanceIdentifier.InstanceIdentifierBuilder<Interface> interfaceInstanceIdentifierBuilder =
+ InstanceIdentifier.builder(Interfaces.class).child(Interface.class, interfaceKey);
+ return interfaceInstanceIdentifierBuilder.build();
+ }
+
+ public static Interface getInterfaceFromConfigDS(InterfaceKey interfaceKey, DataBroker dataBroker) {
+ InstanceIdentifier<Interface> interfaceId = getInterfaceIdentifier(interfaceKey);
+ Optional<Interface> interfaceOptional = IfmUtil.read(LogicalDatastoreType.CONFIGURATION, interfaceId, dataBroker);
+ if (!interfaceOptional.isPresent()) {
+ return null;
+ }
+
+ return interfaceOptional.get();
+ }
+
+ /**
+ * Delete l2 gateway device ucast local macs from elan.<br>
+ * Deletes macs from internal ELAN nodes and also on rest of external l2
+ * gateway devices which are part of the ELAN.
+ *
+ * @param l2GatewayDevice
+ * the l2 gateway device whose ucast local macs to be deleted
+ * from elan
+ * @param elanName
+ * the elan name
+ * @return the listenable future
+ */
+ public static List<ListenableFuture<Void>> deleteL2GwDeviceUcastLocalMacsFromElan(L2GatewayDevice l2GatewayDevice,
+ String elanName) {
+ LOG.info("Deleting L2GatewayDevice [{}] UcastLocalMacs from elan [{}]", l2GatewayDevice.getHwvtepNodeId(), elanName);
+
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ ElanInstance elan = ElanUtils.getElanInstanceByName(elanName);
+ if (elan == null) {
+ LOG.error("Could not find Elan by name: {}", elanName);
+ return futures;
+ }
+
+ List<MacAddress> localMacs = getL2GwDeviceLocalMacs(l2GatewayDevice);
+ unInstallL2GwUcastMacFromElan(elan, l2GatewayDevice, localMacs);
+ return futures;
+ }
+
+ public static void createItmTunnels(ItmRpcService itmRpcService, String hwvtepId, String psName,
+ IpAddress tunnelIp) {
+ AddL2GwDeviceInputBuilder builder = new AddL2GwDeviceInputBuilder();
+ builder.setTopologyId(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID.getValue());
+ builder.setNodeId(HwvtepSouthboundUtils.createManagedNodeId(new NodeId(hwvtepId), psName).getValue());
+ builder.setIpAddress(tunnelIp);
+ try {
+ Future<RpcResult<Void>> result = itmRpcService.addL2GwDevice(builder.build());
+ RpcResult<Void> rpcResult = result.get();
+ if (rpcResult.isSuccessful()) {
+ LOG.info("Created ITM tunnels for {}", hwvtepId);
+ } else {
+ LOG.error("Failed to create ITM Tunnels: ", rpcResult.getErrors());
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("RPC to create ITM tunnels failed", e);
+ }
+ }
+
+ public static String getNodeIdFromDpnId(BigInteger dpnId) {
+ return MDSALUtil.NODE_PREFIX + MDSALUtil.SEPARATOR + dpnId.toString();
+ }
+
+ public static void scheduleAddDpnMacInExtDevices(String elanName, BigInteger dpId,
+ List<PhysAddress> staticMacAddresses) {
+ ConcurrentMap<String, L2GatewayDevice> elanDevices = ElanL2GwCacheUtils
+ .getInvolvedL2GwDevices(elanName);
+ for (final L2GatewayDevice externalDevice : elanDevices.values()) {
+ scheduleAddDpnMacsInExtDevice(elanName, dpId, staticMacAddresses, externalDevice);
+ }
+ }
+
+ public static void scheduleAddDpnMacsInExtDevice(final String elanName, BigInteger dpId,
+ final List<PhysAddress> staticMacAddresses,
+ final L2GatewayDevice externalDevice) {
+ NodeId nodeId = new NodeId(externalDevice.getHwvtepNodeId());
+ final IpAddress dpnTepIp = ElanL2GatewayUtils.getSourceDpnTepIp(dpId, nodeId);
+ LOG.trace("Dpn Tep IP: {} for dpnId: {} and nodeId: {}", dpnTepIp, dpId, nodeId);
+ if (dpnTepIp == null) {
+ LOG.error("could not install dpn mac in l2gw TEP IP not found for dpnId {} and nodeId {}", dpId, nodeId);
+ return;
+ }
+ TerminationPointKey tpKey = HwvtepSouthboundUtils.getTerminationPointKey(
+ dpnTepIp.getIpv4Address().getValue());
+ InstanceIdentifier<TerminationPoint> tpPath = HwvtepSouthboundUtils.createTerminationPointId
+ (nodeId, tpKey);
+
+ HwvtepPhysicalLocatorListener.runJobAfterPhysicalLocatorIsAvialable(tpPath, new Runnable() {
+ @Override
+ public void run() {
+ HwvtepUtils.installUcastMacs(broker,
+ externalDevice.getHwvtepNodeId(), staticMacAddresses,
+ elanName, dpnTepIp);
+ }
+ });
+ }
+
+ public static void scheduleDeleteLogicalSwitch(final NodeId hwvtepNodeId, final String lsName) {
+ TimerTask logicalSwitchDeleteTask = new TimerTask() {
+ @Override
+ public void run() {
+ LogicalSwitchDeletedJob logicalSwitchDeletedJob = new LogicalSwitchDeletedJob(broker, hwvtepNodeId,
+ lsName);
+ ElanL2GatewayUtils.dataStoreJobCoordinator.enqueueJob(logicalSwitchDeletedJob.getJobKey(),
+ logicalSwitchDeletedJob, SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
+ }
+ };
+ Pair<NodeId, String> nodeIdLogicalSwitchNamePair = new ImmutablePair<NodeId, String>(hwvtepNodeId, lsName);
+ LogicalSwitchDeletedTasks.putIfAbsent(nodeIdLogicalSwitchNamePair, logicalSwitchDeleteTask);
+ LogicalSwitchDeleteJobTimer.schedule(logicalSwitchDeleteTask, LOGICAL_SWITCH_DELETE_DELAY);
+ }
+
+ public static void cancelDeleteLogicalSwitch(final NodeId hwvtepNodeId, final String lsName) {
+ Pair<NodeId, String> nodeIdLogicalSwitchNamePair = new ImmutablePair<NodeId, String>(hwvtepNodeId, lsName);
+ TimerTask logicalSwitchDeleteTask = LogicalSwitchDeletedTasks.get(nodeIdLogicalSwitchNamePair);
+ if (logicalSwitchDeleteTask != null) {
+ LOG.debug("Delete logical switch {} action on node {} cancelled", lsName, hwvtepNodeId);
+ logicalSwitchDeleteTask.cancel();
+ LogicalSwitchDeletedTasks.remove(nodeIdLogicalSwitchNamePair);
+ }
+ }
+}
--- /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.l2gw.utils;
+
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.elanmanager.utils.ElanL2GwCacheUtils;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.elan.internal.ElanInstanceManager;
+import org.opendaylight.vpnservice.elan.l2gw.jobs.AssociateHwvtepToElanJob;
+import org.opendaylight.vpnservice.elan.l2gw.jobs.DisAssociateHwvtepFromElanJob;
+import org.opendaylight.vpnservice.elan.l2gw.listeners.HwvtepLogicalSwitchListener;
+import org.opendaylight.vpnservice.elan.utils.ElanClusterUtils;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.utils.L2GatewayCacheUtils;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.Devices;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.connections.attributes.L2gatewayConnections;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.connections.attributes.l2gatewayconnections.L2gatewayConnection;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateways.attributes.L2gateways;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateways.attributes.l2gateways.L2gateway;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateways.attributes.l2gateways.L2gatewayKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.instances.ElanInstance;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class L2GatewayConnectionUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(L2GatewayConnectionUtils.class);
+
+ private static DataBroker broker;
+ private static ElanInstanceManager elanInstanceManager;
+
+ static DataStoreJobCoordinator dataStoreJobCoordinator;
+
+ public static void setDataStoreJobCoordinator(DataStoreJobCoordinator ds) {
+ dataStoreJobCoordinator = ds;
+ }
+
+ public static void setBroker(DataBroker broker) {
+ L2GatewayConnectionUtils.broker = broker;
+ }
+
+ public static void setElanInstanceManager(ElanInstanceManager elanInstanceManager) {
+ L2GatewayConnectionUtils.elanInstanceManager = elanInstanceManager;
+ }
+
+ public static boolean isGatewayAssociatedToL2Device(L2GatewayDevice l2GwDevice) {
+ return (l2GwDevice.getL2GatewayIds().size() > 0);
+ }
+
+ public static L2gateway getNeutronL2gateway(DataBroker broker, Uuid l2GatewayId) {
+ LOG.debug("getNeutronL2gateway for {}", l2GatewayId.getValue());
+ InstanceIdentifier<L2gateway> inst = InstanceIdentifier.create(Neutron.class).child(L2gateways.class)
+ .child(L2gateway.class, new L2gatewayKey(l2GatewayId));
+ Optional<L2gateway> l2Gateway = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, inst);
+ if (l2Gateway.isPresent()) {
+ return l2Gateway.get();
+ }
+ return null;
+ }
+
+ public static List<L2gateway> getL2gatewayList(DataBroker broker) {
+ InstanceIdentifier<L2gateways> inst = InstanceIdentifier.create(Neutron.class).child(L2gateways.class);
+ Optional<L2gateways> l2gateways = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, inst);
+
+ if (l2gateways.isPresent()) {
+ return l2gateways.get().getL2gateway();
+ }
+ return null;
+ }
+
+ public static List<L2gatewayConnection> getAllL2gatewayConnections(DataBroker broker) {
+ InstanceIdentifier<L2gatewayConnections> inst = InstanceIdentifier.create(Neutron.class)
+ .child(L2gatewayConnections.class);
+ Optional<L2gatewayConnections> l2GwConns = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, inst);
+ if (l2GwConns.isPresent()) {
+ return l2GwConns.get().getL2gatewayConnection();
+ }
+ return null;
+ }
+
+ public static void addL2GatewayConnection(L2gatewayConnection input) {
+ addL2GatewayConnection(input, null/*deviceName*/);
+ }
+
+ public static void addL2GatewayConnection(L2gatewayConnection input, String l2GwDeviceName) {
+ LOG.info("Adding L2gateway Connection with ID: {}", input.getKey().getUuid());
+
+ Uuid networkUuid = input.getNetworkId();
+ ElanInstance elanInstance = elanInstanceManager.getElanInstanceByName(networkUuid.getValue());
+ if (elanInstance == null || elanInstance.getVni() == null) {
+ LOG.error("Neutron network with id {} is not present", networkUuid.getValue());
+ } else {
+ Uuid l2GatewayId = input.getL2gatewayId();
+ L2gateway l2Gateway = getNeutronL2gateway(broker, l2GatewayId);
+ if (l2Gateway == null) {
+ LOG.error("L2Gateway with id {} is not present", l2GatewayId.getValue());
+ } else {
+ associateHwvtepsToElan(elanInstance, l2Gateway, input, l2GwDeviceName);
+ }
+ }
+ }
+
+ public static void deleteL2GatewayConnection(L2gatewayConnection input) {
+ LOG.info("Deleting L2gateway Connection with ID: {}", input.getKey().getUuid());
+
+ Uuid networkUuid = input.getNetworkId();
+ ElanInstance elanInstance = elanInstanceManager.getElanInstanceByName(networkUuid.getValue());
+ if (elanInstance == null) {
+ LOG.error("Neutron network with id {} is not present", networkUuid.getValue());
+ } else {
+ Uuid l2GatewayId = input.getL2gatewayId();
+ L2gateway l2Gateway = L2GatewayConnectionUtils.getNeutronL2gateway(broker, l2GatewayId);
+ if (l2Gateway == null) {
+ LOG.error("L2Gateway with id {} is not present", l2GatewayId.getValue());
+ } else {
+ disAssociateHwvtepsFromElan(elanInstance, l2Gateway, input);
+ }
+ }
+ }
+
+ private static void disAssociateHwvtepsFromElan(ElanInstance elanInstance, L2gateway l2Gateway,
+ L2gatewayConnection input) {
+ String elanName = elanInstance.getElanInstanceName();
+ Integer defaultVlan = input.getSegmentId();
+ List<Devices> l2Devices = l2Gateway.getDevices();
+ for (Devices l2Device : l2Devices) {
+ String l2DeviceName = l2Device.getDeviceName();
+ L2GatewayDevice l2GatewayDevice = L2GatewayCacheUtils.getL2DeviceFromCache(l2DeviceName);
+ if (isL2GwDeviceConnected(l2GatewayDevice)) {//TODO handle delete while device is offline
+ // Delete L2 Gateway device from 'ElanL2GwDevice' cache
+ String hwvtepNodeId = l2GatewayDevice.getHwvtepNodeId();
+ boolean isLastL2GwConnDeleted = false;
+ L2GatewayDevice elanL2GwDevice = ElanL2GwCacheUtils.getL2GatewayDeviceFromCache(elanName, hwvtepNodeId);
+ if (isLastL2GwConnBeingDeleted(elanL2GwDevice)) {
+ LOG.debug("Elan L2Gw Conn cache removed for id {}", hwvtepNodeId);
+ ElanL2GwCacheUtils.removeL2GatewayDeviceFromCache(elanName, hwvtepNodeId);
+ isLastL2GwConnDeleted = true;
+ } else {
+ Uuid l2GwConnId = input.getKey().getUuid();
+ LOG.debug("Elan L2Gw Conn cache with id {} is being referred by other L2Gw Conns; so only " +
+ "L2 Gw Conn {} reference is removed", hwvtepNodeId, l2GwConnId);
+ elanL2GwDevice.removeL2GatewayId(l2GwConnId);
+ }
+
+ DisAssociateHwvtepFromElanJob disAssociateHwvtepToElanJob = new DisAssociateHwvtepFromElanJob(broker,
+ elanL2GwDevice, elanInstance, l2Device, defaultVlan, isLastL2GwConnDeleted);
+ ElanClusterUtils.runOnlyInLeaderNode(disAssociateHwvtepToElanJob.getJobKey(),
+ "remove l2gw connection job ",
+ disAssociateHwvtepToElanJob);
+ } else {
+ LOG.info("L2GwConn delete is not handled for device with id {} as it's not connected", l2DeviceName);
+ }
+ }
+ }
+
+ private static void associateHwvtepsToElan(ElanInstance elanInstance,
+ L2gateway l2Gateway, L2gatewayConnection input, String l2GwDeviceName) {
+ String elanName = elanInstance.getElanInstanceName();
+ Integer defaultVlan = input.getSegmentId();
+ Uuid l2GwConnId = input.getKey().getUuid();
+ List<Devices> l2Devices = l2Gateway.getDevices();
+
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Associating ELAN {} with L2Gw Conn Id {} having below L2Gw devices {}", elanName, l2GwConnId,
+ l2Devices);
+ }
+
+ for (Devices l2Device : l2Devices) {
+ String l2DeviceName = l2Device.getDeviceName();
+ // L2gateway can have more than one L2 Gw devices. Configure Logical Switch, VLAN mappings,...
+ // only on the switch which has come up just now and exclude all other devices from
+ // preprovisioning/re-provisioning
+ if (l2GwDeviceName != null && !l2GwDeviceName.equals(l2DeviceName)) {
+ LOG.debug("Associating Hwvtep to ELAN is not been processed for {}; as only {} got connected now!",
+ l2DeviceName, l2GwDeviceName);
+ continue;
+ }
+ L2GatewayDevice l2GatewayDevice = L2GatewayCacheUtils.getL2DeviceFromCache(l2DeviceName);
+ if (isL2GwDeviceConnected(l2GatewayDevice)) {
+ NodeId hwvtepNodeId = new NodeId(l2GatewayDevice.getHwvtepNodeId());
+
+ // Delete pending delete logical switch task if scheduled
+ ElanL2GatewayUtils.cancelDeleteLogicalSwitch(hwvtepNodeId,
+ ElanL2GatewayUtils.getLogicalSwitchFromElan(elanName));
+
+ // Add L2 Gateway device to 'ElanL2GwDevice' cache
+ boolean createLogicalSwitch;
+ LogicalSwitches logicalSwitch = HwvtepUtils.getLogicalSwitch(broker, LogicalDatastoreType.OPERATIONAL,
+ hwvtepNodeId, elanName);
+ if (logicalSwitch == null) {
+ HwvtepLogicalSwitchListener hwVTEPLogicalSwitchListener = new HwvtepLogicalSwitchListener(
+ l2GatewayDevice, elanName, l2Device, defaultVlan, l2GwConnId);
+ hwVTEPLogicalSwitchListener.registerListener(LogicalDatastoreType.OPERATIONAL, broker);
+ createLogicalSwitch = true;
+ } else {
+ addL2DeviceToElanL2GwCache(elanName, l2GatewayDevice, l2GwConnId);
+ createLogicalSwitch = false;
+ }
+ AssociateHwvtepToElanJob associateHwvtepToElanJob = new AssociateHwvtepToElanJob(broker,
+ l2GatewayDevice, elanInstance, l2Device, defaultVlan, createLogicalSwitch);
+
+ ElanClusterUtils.runOnlyInLeaderNode( associateHwvtepToElanJob.getJobKey() ,
+ "create logical switch in hwvtep topo",
+ associateHwvtepToElanJob);
+
+ } else {
+ LOG.info("L2GwConn create is not handled for device with id {} as it's not connected", l2DeviceName);
+ }
+ }
+ }
+
+ public static L2GatewayDevice addL2DeviceToElanL2GwCache(String elanName, L2GatewayDevice l2GatewayDevice,
+ Uuid l2GwConnId) {
+ String l2gwDeviceNodeId = l2GatewayDevice.getHwvtepNodeId();
+ L2GatewayDevice elanL2GwDevice = ElanL2GwCacheUtils.getL2GatewayDeviceFromCache(elanName, l2gwDeviceNodeId);
+ if (elanL2GwDevice == null) {
+ elanL2GwDevice = new L2GatewayDevice();
+ elanL2GwDevice.setHwvtepNodeId(l2gwDeviceNodeId);
+ elanL2GwDevice.setDeviceName(l2GatewayDevice.getDeviceName());
+ elanL2GwDevice.setTunnelIps(l2GatewayDevice.getTunnelIps());
+ ElanL2GwCacheUtils.addL2GatewayDeviceToCache(elanName, elanL2GwDevice);
+ LOG.debug("Elan L2GwConn cache created for hwvtep id {}", l2gwDeviceNodeId);
+ } else {
+ LOG.debug("Elan L2GwConn cache already exists for hwvtep id {}; updating L2GwConn id {} to it",
+ l2gwDeviceNodeId, l2GwConnId);
+ }
+ elanL2GwDevice.addL2GatewayId(l2GwConnId);
+
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Elan L2GwConn cache updated with below details: {}", elanL2GwDevice);
+ }
+ return elanL2GwDevice;
+ }
+
+ private static boolean isL2GwDeviceConnected(L2GatewayDevice l2GwDevice) {
+ return (l2GwDevice != null && l2GwDevice.getHwvtepNodeId() != null && l2GwDevice.isConnected());
+ }
+
+ protected static boolean isLastL2GwConnBeingDeleted(L2GatewayDevice l2GwDevice) {
+ return (l2GwDevice.getL2GatewayIds().size() == 1);
+ }
+}
--- /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.statusanddiag;
+
+import java.lang.management.ManagementFactory;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ElanStatusMonitor implements ElanStatusMonitorMBean{
+
+ private String serviceStatus;
+ private static ElanStatusMonitor elanStatusMonitor = new ElanStatusMonitor();
+ private static final String JMX_ELAN_OBJ_NAME = "com.ericsson.sdncp.services.status:type=SvcElanService";
+ private static final Logger log = LoggerFactory.getLogger(ElanStatusMonitor.class);
+
+ private ElanStatusMonitor () {
+ }
+
+ public void registerMbean() {
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ try {
+ ObjectName objName = new ObjectName(JMX_ELAN_OBJ_NAME);
+ mbs.registerMBean(elanStatusMonitor, objName);
+ log.info("MXBean registration SUCCESSFUL!!! {}", JMX_ELAN_OBJ_NAME);
+ } catch (InstanceAlreadyExistsException iaeEx) {
+ log.error("MXBean registration FAILED with InstanceAlreadyExistsException", iaeEx);
+ } catch (MBeanRegistrationException mbrEx) {
+ log.error("MXBean registration FAILED with MBeanRegistrationException", mbrEx);
+ } catch (NotCompliantMBeanException ncmbEx) {
+ log.error("MXBean registration FAILED with NotCompliantMBeanException", ncmbEx);
+ } catch (MalformedObjectNameException monEx) {
+ log.error("MXBean registration failed with MalformedObjectNameException", monEx);
+ }
+ }
+
+ public static ElanStatusMonitor getInstance() {
+ return elanStatusMonitor;
+ }
+
+ @Override
+ public String acquireServiceStatus() {
+ return serviceStatus;
+ }
+
+ public void reportStatus (String serviceStatus) {
+ this.serviceStatus = serviceStatus;
+ }
+}
\ 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.statusanddiag;
+
+public interface ElanStatusMonitorMBean {
+
+ public String acquireServiceStatus();
+
+}
--- /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 com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.utils.SystemPropertyReader;
+import org.opendaylight.vpnservice.utils.clustering.ClusteringUtils;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepSouthboundConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+
+public class ElanClusterUtils {
+ private static final Logger logger = LoggerFactory.getLogger(ElanClusterUtils.class);
+
+ private static EntityOwnershipService eos;
+
+ static DataStoreJobCoordinator dataStoreJobCoordinator;
+
+ public static void setDataStoreJobCoordinator(DataStoreJobCoordinator ds) {
+ dataStoreJobCoordinator = ds;
+ }
+
+ public static void setEntityOwnershipService(EntityOwnershipService entityOwnershipService) {
+ eos = entityOwnershipService;
+ }
+
+ public static void runOnlyInLeaderNode(Runnable job) {
+ runOnlyInLeaderNode(job, "");
+ }
+
+ public static void runOnlyInLeaderNode(final Runnable job, final String jobDescription) {
+ ListenableFuture<Boolean> checkEntityOwnerFuture = ClusteringUtils.checkNodeEntityOwner(
+ eos, HwvtepSouthboundConstants.ELAN_ENTITY_TYPE,
+ HwvtepSouthboundConstants.ELAN_ENTITY_NAME);
+ Futures.addCallback(checkEntityOwnerFuture, new FutureCallback<Boolean>() {
+ @Override
+ public void onSuccess(Boolean isOwner) {
+ if (isOwner) {
+ job.run();
+ } else {
+ logger.trace("job is not run as i m not cluster owner desc :{} ", jobDescription);
+ }
+ }
+ @Override
+ public void onFailure(Throwable error) {
+ logger.error("Failed to identity cluster owner ", error);
+ }
+ });
+ }
+
+ public static void runOnlyInLeaderNode(String jobKey, Callable<List<ListenableFuture<Void>>> dataStoreJob) {
+ runOnlyInLeaderNode(jobKey, "", dataStoreJob);
+ }
+
+ public static void runOnlyInLeaderNode(final String jobKey, final String jobDescription,
+ final Callable<List<ListenableFuture<Void>>> dataStoreJob) {
+ ListenableFuture<Boolean> checkEntityOwnerFuture = ClusteringUtils.checkNodeEntityOwner(
+ eos, HwvtepSouthboundConstants.ELAN_ENTITY_TYPE,
+ HwvtepSouthboundConstants.ELAN_ENTITY_NAME);
+ Futures.addCallback(checkEntityOwnerFuture, new FutureCallback<Boolean>() {
+ @Override
+ public void onSuccess(Boolean isOwner) {
+ if (isOwner) {
+ logger.trace("scheduling job {} ", jobDescription);
+ dataStoreJobCoordinator.enqueueJob(jobKey, dataStoreJob,
+ SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
+ } else {
+ logger.trace("job is not run as i m not cluster owner desc :{} ", jobDescription);
+ }
+ }
+ @Override
+ public void onFailure(Throwable error) {
+ logger.error("Failed to identity cluster owner for job "+jobDescription, error);
+ }
+ });
+ }
+}
--- /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 = 5000;
+ 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);
+
+ public static final String L2GATEWAY_DS_JOB_NAME = "L2GW";
+ public static final String UNKNOWN_DMAC = "00:00:00:00:00:00";
+ public static final int JOB_MAX_RETRIES = 3;
+}
--- /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;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.apache.commons.lang3.StringUtils;
+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.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.vpnservice.elan.internal.ElanInstanceManager;
+import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
+import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceServiceUtil;
+import org.opendaylight.vpnservice.itm.globals.ITMConstants;
+import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
+import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
+import org.opendaylight.vpnservice.mdsalutil.InstructionType;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil.MdsalOp;
+import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+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.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus;
+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.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+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.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+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.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.ServicesInfo;
+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 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.ElanInstances;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanInterfaceForwardingEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanTagNameMap;
+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.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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
+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.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
+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.GetEgressActionsForInterfaceInput;
+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.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.ExternalTunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnelKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.CreateTerminatingServiceActionsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.CreateTerminatingServiceActionsInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.RemoveTerminatingServiceActionsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.RemoveTerminatingServiceActionsInputBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class ElanUtils {
+
+ private static OdlInterfaceRpcService interfaceMgrRpcService;
+
+ private static ItmRpcService itmRpcService;
+
+ private static IMdsalApiManager mdsalMgr;
+
+ private static DataBroker dataBroker;
+
+ private static final Logger logger = LoggerFactory.getLogger(ElanUtils.class);
+
+ public static final FutureCallback<Void> DEFAULT_CALLBACK = new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(Void result) {
+ logger.debug("Success in Datastore operation");
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ logger.error("Error in Datastore operation", error);
+ }
+ };
+
+ /**
+ * Uses the IdManager to retrieve a brand new ElanTag.
+ *
+ * @param idManager
+ * the id manager
+ * @param idKey
+ * the id key
+ * @return the integer
+ */
+ public static Integer retrieveNewElanTag(IdManagerService idManager, String idKey) {
+
+ AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(ElanConstants.ELAN_ID_POOL_NAME)
+ .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 DataBroker getDataBroker() {
+ return dataBroker;
+ }
+
+ public final static void setIfaceMgrRpcService(OdlInterfaceRpcService rpcService) {
+ interfaceMgrRpcService = rpcService;
+ }
+
+ public final static void setItmRpcService(ItmRpcService itmService) {
+ itmRpcService = itmService;
+ }
+
+ public final static void setDataBroker(DataBroker broker) {
+ dataBroker = broker;
+ }
+
+ public final static void setMdsalManager(IMdsalApiManager mdsalApiManager) {
+ mdsalMgr = mdsalApiManager;
+ }
+
+ 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 != null ) ? broker.newReadOnlyTransaction() : dataBroker.newReadOnlyTransaction();
+ Optional<T> result = Optional.absent();
+ try {
+ CheckedFuture<Optional<T>, ReadFailedException> checkedFuture = tx.read(datastoreType, path);
+ result = checkedFuture.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() {
+ return InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class).build();
+ }
+
+ //elan-instances config container
+ public static ElanInstance getElanInstanceByName(String elanInstanceName) {
+ InstanceIdentifier<ElanInstance> elanIdentifierId = getElanInstanceConfigurationDataPath(elanInstanceName);
+ Optional<ElanInstance> elanInstance = read(dataBroker, 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) {
+ InstanceIdentifier<ElanInterface> elanInterfaceId = getElanInterfaceConfigurationDataPathId(elanInterfaceName);
+ Optional<ElanInterface> existingElanInterface = read(dataBroker, LogicalDatastoreType.CONFIGURATION, elanInterfaceId);
+ if(existingElanInterface.isPresent()) {
+ return existingElanInterface.get();
+ }
+ return null;
+ }
+
+ 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) {
+ InstanceIdentifier<Elan> elanIdentifier = getElanInstanceOperationalDataPath(elanInstanceName);
+ Optional<Elan> elanInstance = read(dataBroker, 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) {
+ InstanceIdentifier<MacEntry> existingMacEntryId = getInterfaceMacEntriesIdentifierOperationalDataPath(interfaceName, physAddress);
+ Optional<MacEntry> existingInterfaceMacEntry = read(dataBroker, LogicalDatastoreType.OPERATIONAL, existingMacEntryId);
+ if(existingInterfaceMacEntry.isPresent()) {
+ return existingInterfaceMacEntry.get();
+ }
+ return null;
+ }
+
+ public static MacEntry getInterfaceMacEntriesOperationalDataPathFromId(InstanceIdentifier identifier) {
+ Optional<MacEntry> existingInterfaceMacEntry = read(dataBroker, 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) {
+ InstanceIdentifier<MacEntry> macId = getMacEntryOperationalDataPath(elanName, physAddress);
+ Optional<MacEntry> existingElanMacEntry = read(dataBroker, LogicalDatastoreType.OPERATIONAL, macId);
+ if(existingElanMacEntry.isPresent()) {
+ return existingElanMacEntry.get();
+ }
+ return null;
+ }
+
+
+ public static MacEntry getMacEntryFromElanMacId(InstanceIdentifier identifier) {
+ Optional<MacEntry> existingInterfaceMacEntry = read(dataBroker, 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) {
+ InstanceIdentifier<ElanInterfaceMac> elanInterfaceId = getElanInterfaceMacEntriesOperationalDataPath(interfaceName);
+ Optional<ElanInterfaceMac> existingElanInterface = read(dataBroker, LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
+ if(existingElanInterface.isPresent()) {
+ return existingElanInterface.get();
+ }
+ return null;
+ }
+
+ /**
+ * Gets the elan interface mac addresses.
+ *
+ * @param interfaceName
+ * the interface name
+ * @return the elan interface mac addresses
+ */
+ public static List<PhysAddress> getElanInterfaceMacAddresses(String interfaceName) {
+ List<PhysAddress> macAddresses = new ArrayList<PhysAddress>();
+ ElanInterfaceMac elanInterfaceMac = ElanUtils.getElanInterfaceMacByInterfaceName(interfaceName);
+ if (elanInterfaceMac != null && elanInterfaceMac.getMacEntry() != null) {
+ List<MacEntry> macEntries = elanInterfaceMac.getMacEntry();
+ for (MacEntry macEntry : macEntries) {
+ macAddresses.add(macEntry.getMacAddress());
+ }
+ }
+ return macAddresses;
+ }
+
+ public static InstanceIdentifier<ElanInterfaceMac> getElanInterfaceMacEntriesOperationalDataPath(String interfaceName) {
+ return InstanceIdentifier.builder(ElanInterfaceForwardingEntries.class).child(ElanInterfaceMac.class,
+ new ElanInterfaceMacKey(interfaceName)).build();
+ }
+
+ /**
+ * Returns the list of Interfaces that belong to an Elan on an specific DPN.
+ * Data retrieved from Elan's operational DS: elan-dpn-interfaces container
+ *
+ * @param elanInstanceName
+ * name of the Elan to which the interfaces must belong to
+ * @param dpId
+ * Id of the DPN where the interfaces are located
+ * @return
+ */
+ public static DpnInterfaces getElanInterfaceInfoByElanDpn(String elanInstanceName, BigInteger dpId) {
+ InstanceIdentifier<DpnInterfaces> elanDpnInterfacesId =
+ getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId);
+ Optional<DpnInterfaces> elanDpnInterfaces = read(dataBroker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfacesId);
+ if ( elanDpnInterfaces.isPresent() ) {
+ return elanDpnInterfaces.get();
+ }
+ return null;
+ }
+
+ /**
+ * Returns the InstanceIdentifier that points to the Interfaces of an Elan in a
+ * given DPN in the Operational DS.
+ * Data retrieved from Elans's operational DS: dpn-interfaces list
+ *
+ * @param elanInstanceName
+ * name of the Elan to which the interfaces must belong to
+ * @param dpId
+ * Id of the DPN where the interfaces are located
+ * @return
+ */
+ 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) {
+ InstanceIdentifier<ElanTagName> elanId = getElanInfoEntriesOperationalDataPath(elanTag);
+ Optional<ElanTagName> existingElanInfo = ElanUtils.read(dataBroker, 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 Optional<IfIndexInterface> getInterfaceInfoByInterfaceTag(long interfaceTag) {
+ InstanceIdentifier<IfIndexInterface> interfaceId = getInterfaceInfoEntriesOperationalDataPath(interfaceTag);
+ return ElanUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, interfaceId);
+ }
+
+ 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) {
+ InstanceIdentifier<ElanDpnInterfacesList> elanDpnInterfaceId = getElanDpnOperationDataPath(elanName);
+ Optional<ElanDpnInterfacesList> existingElanDpnInterfaces =
+ ElanUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
+ if(existingElanDpnInterfaces.isPresent()) {
+ return existingElanDpnInterfaces.get();
+ }
+ return null;
+ }
+
+ /**
+ * This method is useful get all ELAN participating CSS dpIds to install
+ * program remote dmac entries and updating remote bc groups for tor
+ * integration.
+ *
+ * @param elanInstanceName
+ * the elan instance name
+ * @return list of dpIds
+ */
+ public static List<BigInteger> getParticipatingDPNsInElanInstance(String elanInstanceName) {
+ List<BigInteger> dpIds = new ArrayList<BigInteger>();
+ InstanceIdentifier<ElanDpnInterfacesList> elanDpnInterfaceId = getElanDpnOperationDataPath(elanInstanceName);
+ Optional<ElanDpnInterfacesList> existingElanDpnInterfaces =
+ ElanUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
+ if (!existingElanDpnInterfaces.isPresent()) {
+ return dpIds;
+ }
+ List<DpnInterfaces> dpnInterfaces = existingElanDpnInterfaces.get().getDpnInterfaces();
+ for (DpnInterfaces dpnInterface: dpnInterfaces) {
+ dpIds.add(dpnInterface.getDpId());
+ }
+ return dpIds;
+ }
+
+ /**
+ * To check given dpId is already present in Elan instance. This can be used
+ * to program flow entry in external tunnel table when a new access port
+ * added for first time into the ELAN instance
+ *
+ * @param dpId
+ * the dp id
+ * @param elanInstanceName
+ * the elan instance name
+ * @return true if dpId is already present, otherwise return false
+ */
+ public static boolean isDpnAlreadyPresentInElanInstance(BigInteger dpId, String elanInstanceName) {
+ boolean isDpIdPresent = false;
+ InstanceIdentifier<ElanDpnInterfacesList> elanDpnInterfaceId = getElanDpnOperationDataPath(elanInstanceName);
+ Optional<ElanDpnInterfacesList> existingElanDpnInterfaces =
+ ElanUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
+ if (!existingElanDpnInterfaces.isPresent()) {
+ return isDpIdPresent;
+ }
+ List<DpnInterfaces> dpnInterfaces = existingElanDpnInterfaces.get().getDpnInterfaces();
+ for (DpnInterfaces dpnInterface: dpnInterfaces) {
+ if (dpnInterface.getDpId().equals(dpId)) {
+ isDpIdPresent = true;
+ break;
+ }
+ }
+ return isDpIdPresent;
+ }
+
+ public static ElanDpnInterfaces getElanDpnInterfacesList() {
+ InstanceIdentifier<ElanDpnInterfaces> elanDpnInterfaceId =
+ InstanceIdentifier.builder(ElanDpnInterfaces.class).build();
+ Optional<ElanDpnInterfaces> existingElanDpnInterfaces =
+ ElanUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, elanDpnInterfaceId);
+ if(existingElanDpnInterfaces.isPresent()) {
+ return existingElanDpnInterfaces.get();
+ }
+ return null;
+ }
+
+ public static ElanForwardingTables getElanForwardingList() {
+ InstanceIdentifier<ElanForwardingTables> elanForwardingTableId =
+ InstanceIdentifier.builder(ElanForwardingTables.class).build();
+ Optional<ElanForwardingTables> existingElanForwardingList =
+ ElanUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, elanForwardingTableId);
+ if(existingElanForwardingList.isPresent()) {
+ return existingElanForwardingList.get();
+ }
+ return null;
+ }
+
+ /**
+ * Gets the elan mac table.
+ *
+ * @param elanName
+ * the elan name
+ * @return the elan mac table
+ */
+ public static MacTable getElanMacTable(String elanName) {
+ InstanceIdentifier<MacTable> elanMacTableId = getElanMacTableOperationalDataPath(elanName);
+ Optional<MacTable> existingElanMacTable =
+ ElanUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, elanMacTableId);
+ if (existingElanMacTable.isPresent()) {
+ return existingElanMacTable.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, boolean isSHFlagSet ) {
+ int shBit = (isSHFlagSet) ? 1 : 0;
+ return (BigInteger.valueOf(elanTag)).shiftLeft(24).or(BigInteger.valueOf(shBit));
+ }
+
+ 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);
+ }
+
+ /**
+ * Setting INTERNAL_TUNNEL_TABLE, SMAC, DMAC, UDMAC in this DPN and also in
+ * other DPNs.
+ *
+ * @param elanInfo
+ * the elan info
+ * @param interfaceInfo
+ * the interface info
+ * @param macTimeout
+ * the mac timeout
+ * @param macAddress
+ * the mac address
+ */
+ public static void setupMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, long macTimeout,
+ String macAddress) {
+ synchronized (macAddress) {
+ logger.info("Acquired lock for mac : " + macAddress + ". Proceeding with install operation.");
+ setupKnownSmacFlow(elanInfo, interfaceInfo, macTimeout, macAddress, mdsalMgr);
+ setupOrigDmacFlows(elanInfo, interfaceInfo, macAddress, mdsalMgr, dataBroker);
+ }
+ }
+
+ 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);
+ }
+ }
+
+
+ /**
+ * Inserts a Flow in SMAC table to state that the MAC has already been learnt.
+ *
+ * @param elanInfo
+ * @param interfaceInfo
+ * @param macTimeout
+ * @param macAddress
+ * @param mdsalApiManager
+ */
+ private static void setupKnownSmacFlow(ElanInstance elanInfo, InterfaceInfo interfaceInfo, long macTimeout,
+ String macAddress, IMdsalApiManager mdsalApiManager) {
+ FlowEntity flowEntity = buildKnownSmacFlow(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);
+ }
+ }
+
+ public static FlowEntity buildKnownSmacFlow(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;
+ }
+
+ /**
+ * Installs a Flow in INTERNAL_TUNNEL_TABLE of the affected DPN that sends the packet through the specified
+ * interface if the tunnel_id matches the interface's lportTag
+ *
+ * @param interfaceInfo
+ * @param mdsalApiManager
+ */
+ public static void setupTermDmacFlows(InterfaceInfo interfaceInfo, IMdsalApiManager mdsalApiManager) {
+ BigInteger dpId = interfaceInfo.getDpId();
+ int lportTag = interfaceInfo.getInterfaceTag();
+ Flow flow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
+ getIntTunnelTableFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, lportTag), 5,
+ String.format("%s:%d","ITM Flow Entry ",lportTag), 0, 0,
+ ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(lportTag)),
+ getTunnelIdMatchForFilterEqualsLPortTag(lportTag),
+ getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
+ mdsalApiManager.installFlow(dpId, flow);
+ if (logger.isDebugEnabled()) {
+ logger.debug("Terminating service table flow entry created on dpn:{} for logical Interface port:{}",
+ dpId, interfaceInfo.getPortName());
+ }
+ }
+
+ /**
+ * Constructs the FlowName for flows installed in the Internal Tunnel Table,
+ * consisting in tableId + elanTag.
+ *
+ * @param tableId
+ * @param elanTag
+ * @return
+ */
+ public static String getIntTunnelTableFlowRef(short tableId, int elanTag) {
+ return new StringBuffer().append(tableId).append(elanTag).toString();
+ }
+
+ /**
+ * Constructs the Matches that checks that the tunnel_id field contains a
+ * specific lportTag
+ *
+ * @param lportTag
+ * lportTag that must be checked against the tunnel_id field
+ * @return
+ */
+ public static List<MatchInfo> getTunnelIdMatchForFilterEqualsLPortTag(int lportTag) {
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ // Matching metadata
+ mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {
+ BigInteger.valueOf(lportTag)}));
+ return mkMatches;
+ }
+
+ /**
+ * Constructs the Instructions that take the packet over a given interface
+ *
+ * @param ifName
+ * Name of the interface where the packet must be sent over. It can
+ * be a local interface or a tunnel interface (internal or external)
+ * @return
+ */
+ public static List<Instruction> getInstructionsInPortForOutGroup(String ifName) {
+ List<Instruction> mkInstructions = new ArrayList<Instruction>();
+ List<Action> actions = ElanUtils.getEgressActionsForInterface(ifName, /*tunnelKey*/ null );
+
+ mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions));
+ return mkInstructions;
+ }
+
+
+ /**
+ * Returns the list of Actions to be taken when sending the packet through
+ * an Elan interface. Note that this interface can refer to an ElanInterface
+ * where the Elan VM is attached to a DPN or an ITM tunnel interface where
+ * Elan traffic can be sent through. In this latter case, the tunnelKey is
+ * mandatory and it can hold serviceId for internal tunnels or the VNI for
+ * external tunnels.
+ *
+ * @param ifName
+ * the if name
+ * @param tunnelKey
+ * the tunnel key
+ * @return the egress actions for interface
+ */
+ public static List<Action> getEgressActionsForInterface(String ifName, Long tunnelKey) {
+ List<Action> listAction = new ArrayList<Action>();
+ try {
+ GetEgressActionsForInterfaceInput getEgressActionInput =
+ new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName).setTunnelKey(tunnelKey).build();
+ Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
+ interfaceMgrRpcService.getEgressActionsForInterface(getEgressActionInput);
+ RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
+ 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();
+ listAction = actions;
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ logger.warn("Exception when egress actions for interface {}", ifName, e);
+ }
+ return listAction;
+ }
+
+ 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();
+ String elanInstanceName = elanInfo.getElanInstanceName();
+ List<DpnInterfaces> elanDpns = getInvolvedDpnsInElan(elanInstanceName);
+ if (elanDpns != null) {
+ Long elanTag = elanInfo.getElanTag();
+ for (DpnInterfaces elanDpn : elanDpns) {
+ if (elanDpn.getDpId().equals(dpId)) {
+ // On the local DPN set up a direct output flow
+ setupLocalDmacFlow(elanTag, dpId, ifName, macAddress, elanInstanceName, mdsalApiManager, ifTag);
+ logger.debug("Dmac flow entry created for elan Name:{}, logical port Name:{} and mac address:{} on dpn:{}",
+ elanInstanceName, interfaceInfo.getPortName(), macAddress, dpId);
+ } else {
+ // Check for the Remote DPN present in Inventory Manager
+ if (isDpnPresent(elanDpn.getDpId())) {
+ // For remote DPNs a flow is needed to indicate that packets of this ELAN going to this MAC
+ // need to be forwarded through the appropiated ITM tunnel
+ setupRemoteDmacFlow(elanDpn.getDpId(), // srcDpn (the remote DPN in this case)
+ dpId, // dstDpn (the local DPN)
+ interfaceInfo.getInterfaceTag(), // lportTag of the local interface
+ elanTag, // identifier of the Elan
+ macAddress, // MAC to be programmed in remote DPN
+ elanInstanceName);
+ logger.debug("Dmac flow entry created for elan Name:{}, logical port Name:{} and mac address:{} on dpn:{}",
+ elanInstanceName, interfaceInfo.getPortName(), macAddress, elanDpn.getDpId());
+ }
+ }
+ }
+
+ // TODO (eperefr): Make sure that the same is performed against the ElanDevices.
+ }
+ }
+
+ 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);
+ if (dpns == null) {
+ return Collections.emptyList();
+ }
+ return dpns;
+ }
+
+ private static void setupLocalDmacFlow(long elanTag, BigInteger dpId, String ifName, String macAddress,
+ String displayName, IMdsalApiManager mdsalApiManager, long ifTag) {
+ Flow flowEntity = buildLocalDmacFlowEntry(elanTag, dpId, ifName, macAddress, displayName, ifTag);
+ mdsalApiManager.installFlow(dpId, 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();
+ }
+
+ private static String getKnownDynamicmacFlowRef(short elanDmacTable, BigInteger dpId, String extDeviceNodeId,
+ String dstMacAddress, long elanTag, boolean shFlag) {
+ return new StringBuffer().append(elanDmacTable).append(elanTag).append(dpId)
+ .append(extDeviceNodeId).append(dstMacAddress).append(shFlag)
+ .toString();
+ }
+
+ /**
+ * Builds the flow to be programmed in the DMAC table of the local DPN (that is, where the MAC is attached to).
+ * This flow consists in:
+ *
+ * Match:
+ * + elanTag in metadata
+ * + packet goes to a MAC locally attached
+ * Actions:
+ * + optionally, pop-vlan + set-vlan-id
+ * + output to ifName's portNumber
+ *
+ * @param elanTag the elan tag
+ * @param dpId the dp id
+ * @param ifName the if name
+ * @param macAddress the mac address
+ * @param displayName the display name
+ * @param ifTag the if tag
+ * @return the flow
+ */
+ public static Flow buildLocalDmacFlowEntry(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<Instruction> mkInstructions = new ArrayList<Instruction>();
+ List<Action> actions = getEgressActionsForInterface(ifName, /* tunnelKey */ null);
+ mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions));
+ Flow flow = MDSALUtil.buildFlowNew(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 flow;
+ }
+
+ public static void setupRemoteDmacFlow(BigInteger srcDpId, BigInteger destDpId, int lportTag, long elanTag, String macAddress,
+ String displayName) {
+ Flow flowEntity = buildRemoteDmacFlowEntry(srcDpId, destDpId, lportTag, elanTag, macAddress, displayName);
+ mdsalMgr.installFlow(srcDpId, flowEntity);
+ }
+
+ /**
+ * Builds a Flow to be programmed in a remote DPN's DMAC table.
+ * This flow consists in:
+ * Match:
+ * + elanTag in packet's metadata
+ * + packet going to a MAC known to be located in another DPN
+ * Actions:
+ * + set_tunnel_id(lportTag)
+ * + output ITM internal tunnel interface with the other DPN
+ *
+ * @param srcDpId
+ * @param destDpId
+ * @param lportTag
+ * @param elanTag
+ * @param macAddress
+ * @param displayName
+ * @return
+ */
+ public static Flow buildRemoteDmacFlowEntry(BigInteger srcDpId, BigInteger destDpId, int lportTag, long elanTag,
+ String macAddress, String displayName) {
+ 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<Instruction> mkInstructions = new ArrayList<Instruction>();
+
+ //List of Action for the provided Source and Destination DPIDs
+ try {
+ List<Action> actions = getInternalItmEgressAction(srcDpId, destDpId, lportTag);
+ mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions));
+ } catch (Exception e) {
+ logger.error("Interface Not Found exception");
+ }
+
+
+ Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_DMAC_TABLE,
+ getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, srcDpId, destDpId, macAddress, elanTag),
+ 20, /* prio */
+ displayName, 0, /* idleTimeout */
+ 0, /* hardTimeout */
+ ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches, mkInstructions);
+
+ return flow;
+
+ }
+
+ 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, /* alsoDeleteSMAC */ true);
+ }
+ }
+
+ public static void deleteMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, String macAddress, boolean deleteSmac) {
+ String elanInstanceName = elanInfo.getElanInstanceName();
+ long ifTag = interfaceInfo.getInterfaceTag();
+ List<DpnInterfaces> remoteFEs = getInvolvedDpnsInElan(elanInstanceName);
+ BigInteger srcdpId = interfaceInfo.getDpId();
+ for (DpnInterfaces dpnInterface: remoteFEs) {
+ Long elanTag = elanInfo.getElanTag();
+ BigInteger dstDpId = dpnInterface.getDpId();
+ if (dstDpId.equals(srcdpId)) {
+ if(deleteSmac) {
+ mdsalMgr.removeFlow(srcdpId, MDSALUtil.buildFlow(ElanConstants.ELAN_SMAC_TABLE,
+ getKnownDynamicmacFlowRef(ElanConstants.ELAN_SMAC_TABLE, srcdpId, ifTag, macAddress, elanTag)));
+ }
+ mdsalMgr.removeFlow(srcdpId, MDSALUtil.buildFlow(ElanConstants.ELAN_DMAC_TABLE,
+ getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, srcdpId, ifTag, macAddress, elanTag)));
+ if (logger.isDebugEnabled()) {
+ logger.debug("All the required flows deleted for elan:{}, logical Interface port:{} and mac address:{} on dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, srcdpId);
+ }
+ } else if (isDpnPresent(dstDpId)) {
+ mdsalMgr.removeFlow(dstDpId, MDSALUtil.buildFlow(ElanConstants.ELAN_DMAC_TABLE,
+ getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, dstDpId, srcdpId, macAddress, elanTag)));
+ if (logger.isDebugEnabled()) {
+ logger.debug("Dmac flow entry deleted for elan:{}, logical interface port:{} and mac address:{} on dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, dstDpId);
+ }
+ }
+ }
+ }
+
+ /**
+ * Updates the Elan information in the Operational DS. It also updates the
+ * ElanInstance in the Config DS by setting the adquired elanTag.
+ *
+ * @param broker
+ * the broker
+ * @param idManager
+ * the id manager
+ * @param elanInstanceAdded
+ * the elan instance added
+ */
+ public static void updateOperationalDataStore(DataBroker broker, IdManagerService idManager,
+ ElanInstance elanInstanceAdded) {
+ String elanInstanceName = elanInstanceAdded.getElanInstanceName();
+ long elanTag = ElanUtils.retrieveNewElanTag(idManager, 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);
+
+ // Updates the ElanInstance Config DS by setting the just adquired elanTag
+ 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,
+ getElanInstanceConfigurationDataPath(elanInstanceName), elanInstanceWithTag);
+ }
+
+ public static boolean isDpnPresent(BigInteger dpnId) {
+ 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(dataBroker, LogicalDatastoreType.OPERATIONAL, node);
+ return (nodePresent.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();
+ }
+
+ /**
+ * Builds the list of actions to be taken when sending the packet over a
+ * VxLan Tunnel Interface, such as setting the tunnel_id field, the vlanId
+ * if proceeds and output the packet over the right port.
+ *
+ * @param tunnelIfaceName
+ * the tunnel iface name
+ * @param tunnelKey
+ * the tunnel key
+ * @return the list
+ */
+ public static List<Action> buildItmEgressActions(String tunnelIfaceName, Long tunnelKey) {
+ List<Action> result = Collections.emptyList();
+ if (tunnelIfaceName != null && !tunnelIfaceName.isEmpty()) {
+ GetEgressActionsForInterfaceInput getEgressActInput = new GetEgressActionsForInterfaceInputBuilder()
+ .setIntfName(tunnelIfaceName).setTunnelKey(tunnelKey).build();
+
+ Future<RpcResult<GetEgressActionsForInterfaceOutput>> egressActionsOutputFuture =
+ interfaceMgrRpcService.getEgressActionsForInterface(getEgressActInput);
+ try {
+ if (egressActionsOutputFuture.get().isSuccessful()) {
+ GetEgressActionsForInterfaceOutput egressActionsOutput = egressActionsOutputFuture.get().getResult();
+ result = egressActionsOutput.getAction();
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ logger.error("Error in RPC call getEgressActionsForInterface {}", e);
+ }
+ }
+
+ if ( result == null || result.size() == 0 ) {
+ logger.warn("Could not build Egress actions for interface {} and tunnelId {}", tunnelIfaceName, tunnelKey);
+ }
+ return result;
+ }
+
+ /**
+ * Builds the list of actions to be taken when sending the packet over an
+ * external VxLan tunnel interface, such as stamping the VNI on the VxLAN
+ * header, setting the vlanId if it proceeds and output the packet over the
+ * right port.
+ *
+ * @param srcDpnId
+ * Dpn where the tunnelInterface is located
+ * @param torNode
+ * NodeId of the ExternalDevice where the packet must be sent to.
+ * @param vni
+ * Vni to be stamped on the VxLAN Header.
+ * @return the external itm egress action
+ */
+ public static List<Action> getExternalItmEgressAction(BigInteger srcDpnId, NodeId torNode, long vni ) {
+ List<Action> result = Collections.emptyList();
+
+ GetExternalTunnelInterfaceNameInput input = new GetExternalTunnelInterfaceNameInputBuilder()
+ .setDestinationNode(torNode.getValue()).setSourceNode(srcDpnId.toString()).setTunnelType(TunnelTypeVxlan.class).build();
+ Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> output =
+ itmRpcService.getExternalTunnelInterfaceName(input);
+ try {
+ if (output.get().isSuccessful()) {
+ GetExternalTunnelInterfaceNameOutput tunnelInterfaceNameOutput = output.get().getResult();
+ String tunnelIfaceName = tunnelInterfaceNameOutput.getInterfaceName();
+ if ( logger.isDebugEnabled() )
+ logger.debug("Received tunnelInterfaceName from getTunnelInterfaceName RPC {}", tunnelIfaceName);
+
+ result = buildItmEgressActions(tunnelIfaceName, vni);
+ }
+
+ } catch (InterruptedException | ExecutionException e) {
+ logger.error("Error in RPC call getTunnelInterfaceName {}", e);
+ }
+
+ return result;
+ }
+
+ /**
+ * Builds the list of actions to be taken when sending the packet over an
+ * internal VxLan tunnel interface, such as setting the serviceTag on the
+ * VNI field of the VxLAN header, setting the vlanId if it proceeds and
+ * output the packet over the right port.
+ *
+ * @param sourceDpnId
+ * Dpn where the tunnelInterface is located
+ * @param destinationDpnId
+ * Dpn where the packet must be sent to. It is used here in order
+ * to select the right tunnel interface.
+ * @param serviceTag
+ * serviceId to be sent on the VxLAN header.
+ * @return the internal itm egress action
+ */
+ public static List<Action> getInternalItmEgressAction(BigInteger sourceDpnId, BigInteger destinationDpnId,
+ long serviceTag) {
+ List<Action> result = Collections.emptyList();
+
+ logger.debug("In getInternalItmEgressAction Action source {}, destination {}, elanTag {}",
+ sourceDpnId, destinationDpnId, serviceTag);
+ Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
+ GetTunnelInterfaceNameInput input = new GetTunnelInterfaceNameInputBuilder()
+ .setDestinationDpid(destinationDpnId).setSourceDpid(sourceDpnId).setTunnelType(tunType).build();
+ Future<RpcResult<GetTunnelInterfaceNameOutput>> output = itmRpcService.getTunnelInterfaceName(input);
+ try {
+ if (output.get().isSuccessful()) {
+ GetTunnelInterfaceNameOutput tunnelInterfaceNameOutput = output.get().getResult();
+ String tunnelIfaceName = tunnelInterfaceNameOutput.getInterfaceName();
+ logger.debug("Received tunnelInterfaceName from getTunnelInterfaceName RPC {}", tunnelIfaceName);
+
+ result = buildItmEgressActions(tunnelIfaceName, serviceTag);
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ logger.error("Error in RPC call getTunnelInterfaceName {}", e);
+ }
+
+ return result;
+ }
+
+ public static List<MatchInfo> getTunnelMatchesForServiceId(int elanTag) {
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ // Matching metadata
+ mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[]{BigInteger.valueOf(elanTag)}));
+
+ return mkMatches;
+ }
+
+ public static void removeTerminatingServiceAction(BigInteger destDpId, int serviceId) {
+ RemoveTerminatingServiceActionsInput input = new RemoveTerminatingServiceActionsInputBuilder().setDpnId(destDpId).setServiceId(serviceId).build();
+ Future<RpcResult<Void>> futureObject = itmRpcService.removeTerminatingServiceActions(input);
+ try {
+ RpcResult<Void> result = futureObject.get();
+ if (result.isSuccessful()) {
+ logger.debug("Successfully completed removeTerminatingServiceActions");
+ } else {
+ logger.debug("Failure in removeTerminatingServiceAction RPC call");
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ logger.error("Error in RPC call removeTerminatingServiceActions {}", e);
+ }
+ }
+
+ public static void createTerminatingServiceActions(BigInteger destDpId, int serviceId, List<Action> actions) {
+ List<Instruction> mkInstructions = new ArrayList<Instruction>();
+ mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions));
+ CreateTerminatingServiceActionsInput input = new CreateTerminatingServiceActionsInputBuilder().setDpnId(destDpId).setServiceId(serviceId).setInstruction(mkInstructions).build();
+
+ itmRpcService.createTerminatingServiceActions(input);
+ }
+
+ public static TunnelList buildInternalTunnel(DataBroker broker) {
+ InstanceIdentifier<TunnelList> tunnelListInstanceIdentifier = InstanceIdentifier.builder(TunnelList.class).build();
+ Optional<TunnelList> tunnelList = read(broker, LogicalDatastoreType.CONFIGURATION, tunnelListInstanceIdentifier);
+ if (tunnelList.isPresent()) {
+ return tunnelList.get();
+ }
+ return null;
+ }
+
+ /**
+ * Gets the external tunnel.
+ *
+ * @param sourceDevice
+ * the source device
+ * @param destinationDevice
+ * the destination device
+ * @param datastoreType
+ * the datastore type
+ * @return the external tunnel
+ */
+ public static ExternalTunnel getExternalTunnel(String sourceDevice, String destinationDevice,
+ LogicalDatastoreType datastoreType) {
+ ExternalTunnel externalTunnel = null;
+ Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class ;
+ InstanceIdentifier<ExternalTunnel> iid = InstanceIdentifier.builder(ExternalTunnelList.class)
+ .child(ExternalTunnel.class, new ExternalTunnelKey(destinationDevice, sourceDevice, tunType)).build();
+ Optional<ExternalTunnel> tunnelList = read(dataBroker, datastoreType, iid);
+ if (tunnelList.isPresent()) {
+ externalTunnel = tunnelList.get();
+ }
+ return externalTunnel;
+ }
+
+ /**
+ * Gets the external tunnel.
+ *
+ * @param interfaceName
+ * the interface name
+ * @param datastoreType
+ * the datastore type
+ * @return the external tunnel
+ */
+ public static ExternalTunnel getExternalTunnel(String interfaceName, LogicalDatastoreType datastoreType) {
+ ExternalTunnel externalTunnel = null;
+ List<ExternalTunnel> externalTunnels = getAllExternalTunnels(datastoreType);
+ for (ExternalTunnel tunnel : externalTunnels) {
+ if (StringUtils.equalsIgnoreCase(interfaceName, tunnel.getTunnelInterfaceName())) {
+ externalTunnel = tunnel;
+ break;
+ }
+ }
+ return externalTunnel;
+ }
+
+ /**
+ * Gets the all external tunnels.
+ *
+ * @return the all external tunnels
+ */
+ public static List<ExternalTunnel> getAllExternalTunnels(LogicalDatastoreType datastoreType) {
+ List<ExternalTunnel> result = null;
+ InstanceIdentifier<ExternalTunnelList> iid = InstanceIdentifier.builder(ExternalTunnelList.class).build();
+ Optional<ExternalTunnelList> tunnelList = read(dataBroker, datastoreType, iid);
+ if (tunnelList.isPresent()) {
+ result = tunnelList.get().getExternalTunnel();
+ }
+ if (result == null) {
+ result = Collections.emptyList();
+ }
+ return result;
+ }
+
+ /**
+ * Installs a Flow in a DPN's DMAC table. The Flow is for a MAC that is
+ * connected remotely in another CSS and accessible through an internal
+ * tunnel. It also installs the flow for dropping the packet if it came over
+ * an ITM tunnel (that is, if the Split-Horizon flag is set)
+ *
+ * @param localDpId
+ * Id of the DPN where the MAC Addr is accessible locally
+ * @param remoteDpId
+ * Id of the DPN where the flow must be installed
+ * @param lportTag
+ * lportTag of the interface where the mac is connected to.
+ * @param elanTag
+ * Identifier of the ELAN
+ * @param macAddress
+ * MAC to be installed in remoteDpId's DMAC table
+ * @param displayName
+ * the display name
+ */
+ public static void installDmacFlowsToInternalRemoteMac(BigInteger localDpId, BigInteger remoteDpId, long lportTag,
+ long elanTag, String macAddress, String displayName) {
+ Flow flow = buildDmacFlowForInternalRemoteMac(localDpId, remoteDpId, lportTag, elanTag, macAddress, displayName);
+ mdsalMgr.installFlow(remoteDpId, flow);
+ }
+
+ /**
+ * Installs a Flow in the specified DPN's DMAC table. The flow is for a MAC
+ * that is connected remotely in an External Device (TOR) and that is
+ * accessible through an external tunnel. It also installs the flow for
+ * dropping the packet if it came over an ITM tunnel (that is, if the
+ * Split-Horizon flag is set)
+ *
+ * @param dpnId
+ * Id of the DPN where the flow must be installed
+ * @param extDeviceNodeId
+ * the ext device node id
+ * @param elanTag
+ * the elan tag
+ * @param vni
+ * the vni
+ * @param macAddress
+ * the mac address
+ * @param displayName
+ * the display name
+ */
+ public static List<ListenableFuture<Void>> installDmacFlowsToExternalRemoteMac(BigInteger dpnId,
+ String extDeviceNodeId, Long elanTag, Long vni, String macAddress, String displayName) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ synchronized (macAddress) {
+ Flow flow = buildDmacFlowForExternalRemoteMac(dpnId, extDeviceNodeId, elanTag, vni, macAddress, displayName);
+ futures.add(mdsalMgr.installFlow(dpnId, flow));
+
+ Flow dropFlow = buildDmacFlowDropIfPacketComingFromTunnel(dpnId, extDeviceNodeId, elanTag, macAddress);
+ futures.add(mdsalMgr.installFlow(dpnId, dropFlow));
+ }
+ return futures;
+ }
+
+ public static List<MatchInfo> buildMatchesForElanTagShFlagAndDstMac(long elanTag, boolean shFlag, String macAddr) {
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ mkMatches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ ElanUtils.getElanMetadataLabel(elanTag, shFlag), MetaDataUtil.METADATA_MASK_SERVICE_SH_FLAG }));
+ mkMatches.add(new MatchInfo(MatchFieldType.eth_dst, new String[] { macAddr }));
+
+ return mkMatches;
+ }
+
+ /**
+ * Builds a Flow to be programmed in a DPN's DMAC table. This method must be used when the MAC is located in an
+ * External Device (TOR).
+ * The flow matches on the specified MAC and
+ * 1) sends the packet over the CSS-TOR tunnel if SHFlag is not set, or
+ * 2) drops it if SHFlag is set (what means the packet came from an external tunnel)
+ *
+ * @param dpId DPN whose DMAC table is going to be modified
+ * @param extDeviceNodeId Hwvtep node where the mac is attached to
+ * @param elanTag ElanId to which the MAC is being added to
+ * @param vni the vni
+ * @param dstMacAddress The mac address to be programmed
+ * @param displayName the display name
+ * @return the flow
+ */
+ public static Flow buildDmacFlowForExternalRemoteMac(BigInteger dpId, String extDeviceNodeId, long elanTag,
+ Long vni, String dstMacAddress, String displayName ) {
+ List<MatchInfo> mkMatches = buildMatchesForElanTagShFlagAndDstMac(elanTag, /*shFlag*/ false, dstMacAddress);
+ List<Instruction> mkInstructions = new ArrayList<Instruction>();
+ try {
+ List<Action> actions = getExternalItmEgressAction(dpId, new NodeId(extDeviceNodeId), vni);
+ mkInstructions.add( MDSALUtil.buildApplyActionsInstruction(actions) );
+ } catch (Exception e) {
+ logger.error("Could not get Egress Actions for DpId={} externalNode={}", dpId, extDeviceNodeId );
+ }
+
+ Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_DMAC_TABLE,
+ getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, dpId, extDeviceNodeId, dstMacAddress, elanTag,
+ false),
+ 20, /* prio */
+ displayName, 0, /* idleTimeout */
+ 0, /* hardTimeout */
+ ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches, mkInstructions);
+
+ return flow;
+ }
+
+ /**
+ * Builds the flow that drops the packet if it came through an external tunnel, that is, if the Split-Horizon
+ * flag is set.
+ *
+ * @param dpnId DPN whose DMAC table is going to be modified
+ * @param extDeviceNodeId Hwvtep node where the mac is attached to
+ * @param elanTag ElanId to which the MAC is being added to
+ * @param dstMacAddress The mac address to be programmed
+ * @param displayName
+ * @return
+ */
+ private static Flow buildDmacFlowDropIfPacketComingFromTunnel(BigInteger dpnId, String extDeviceNodeId,
+ Long elanTag, String dstMacAddress) {
+ List<MatchInfo> mkMatches = buildMatchesForElanTagShFlagAndDstMac(elanTag, /*shFlag*/ true, dstMacAddress);
+ List<Instruction> mkInstructions = MDSALUtil.buildInstructionsDrop();
+ String flowId = getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, dpnId, extDeviceNodeId, dstMacAddress,
+ elanTag, true);
+ Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_DMAC_TABLE, flowId, 20, /* prio */
+ "Drop", 0, /* idleTimeout */
+ 0, /* hardTimeout */
+ ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches, mkInstructions);
+
+ return flow;
+ }
+
+ private static String getDmacDropFlowId(Long elanTag, String dstMacAddress) {
+ return new StringBuilder(ElanConstants.ELAN_DMAC_TABLE).append(elanTag).append(dstMacAddress).append("Drop")
+ .toString();
+ }
+
+ /**
+ * Builds a Flow to be programmed in a remote DPN's DMAC table. This method must be used when the MAC is located
+ * in another CSS.
+ *
+ * This flow consists in:
+ * Match:
+ * + elanTag in packet's metadata
+ * + packet going to a MAC known to be located in another DPN
+ * Actions:
+ * + set_tunnel_id(lportTag)
+ * + output on ITM internal tunnel interface with the other DPN
+ *
+ * @param localDpId the local dp id
+ * @param remoteDpId the remote dp id
+ * @param lportTag the lport tag
+ * @param elanTag the elan tag
+ * @param macAddress the mac address
+ * @param displayName the display name
+ * @return the flow
+ */
+ public static Flow buildDmacFlowForInternalRemoteMac(BigInteger localDpId, BigInteger remoteDpId, long lportTag,
+ long elanTag, String macAddress, String displayName) {
+ List<MatchInfo> mkMatches = buildMatchesForElanTagShFlagAndDstMac(elanTag, /*shFlag*/ false, macAddress);
+
+ List<Instruction> mkInstructions = new ArrayList<Instruction>();
+
+ try {
+ //List of Action for the provided Source and Destination DPIDs
+ List<Action> actions = getInternalItmEgressAction(localDpId, remoteDpId, lportTag);
+ mkInstructions.add( MDSALUtil.buildApplyActionsInstruction(actions) );
+ } catch (Exception e) {
+ logger.error("Could not get Egress Actions for localDpId={} remoteDpId={} lportTag={}",
+ localDpId, remoteDpId, lportTag);
+ }
+
+ Flow flow = MDSALUtil.buildFlowNew(ElanConstants.ELAN_DMAC_TABLE,
+ getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, localDpId, remoteDpId, macAddress, elanTag),
+ 20, /* prio */
+ displayName, 0, /* idleTimeout */
+ 0, /* hardTimeout */
+ ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches, mkInstructions);
+
+ return flow;
+
+ }
+
+ /**
+ * Installs or removes flows in DMAC table for MACs that are/were located in
+ * an external Elan Device.
+ *
+ * @param dpId
+ * Id of the DPN where the DMAC table is going to be modified
+ * @param extNodeId
+ * Id of the External Device where the MAC is located
+ * @param elanTag
+ * Id of the ELAN
+ * @param vni
+ * VNI of the LogicalSwitch to which the MAC belongs to, and that
+ * is associated with the ELAN
+ * @param macAddress
+ * the mac address
+ * @param elanInstanceName
+ * the elan instance name
+ * @param addOrRemove
+ * Indicates if flows must be installed or removed.
+ * @see org.opendaylight.vpnservice.mdsalutil.MDSALUtil.MdsalOp
+ */
+ public static void setupDmacFlowsToExternalRemoteMac(BigInteger dpId, String extNodeId, Long elanTag, Long vni,
+ String macAddress, String elanInstanceName, MdsalOp addOrRemove) {
+ if ( addOrRemove == MdsalOp.CREATION_OP ) {
+ ElanUtils.installDmacFlowsToExternalRemoteMac(dpId, extNodeId, elanTag, vni, macAddress, elanInstanceName);
+ } else if ( addOrRemove == MdsalOp.REMOVAL_OP ) {
+ ElanUtils.deleteDmacFlowsToExternalMac(elanTag, dpId, extNodeId, macAddress );
+ }
+ }
+
+ /**
+ * Delete dmac flows to external mac.
+ *
+ * @param elanTag
+ * the elan tag
+ * @param dpId
+ * the dp id
+ * @param extDeviceNodeId
+ * the ext device node id
+ * @param macToRemove
+ * the mac to remove
+ */
+ public static List<ListenableFuture<Void>> deleteDmacFlowsToExternalMac(long elanTag, BigInteger dpId,
+ String extDeviceNodeId, String macToRemove ) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ synchronized (macToRemove) {
+ // Removing the flows that sends the packet on an external tunnel
+ String flowId = getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, dpId, extDeviceNodeId,
+ macToRemove, elanTag, false);
+ Flow flowToRemove = new FlowBuilder().setId(new FlowId(flowId)).setTableId(ElanConstants.ELAN_DMAC_TABLE)
+ .build();
+ futures.add(mdsalMgr.removeFlow(dpId, flowToRemove));
+
+ // And now removing the drop flow
+ flowId = getKnownDynamicmacFlowRef(ElanConstants.ELAN_DMAC_TABLE, dpId, extDeviceNodeId, macToRemove,
+ elanTag, true);
+ flowToRemove = new FlowBuilder().setId(new FlowId(flowId)).setTableId(ElanConstants.ELAN_DMAC_TABLE)
+ .build();
+ futures.add(mdsalMgr.removeFlow(dpId, flowToRemove));
+ }
+ return futures;
+ }
+
+ /**
+ * Gets the dpid from interface.
+ *
+ * @param interfaceName
+ * the interface name
+ * @return the dpid from interface
+ */
+ public static BigInteger getDpidFromInterface(String interfaceName) {
+ BigInteger dpId = null;
+ Future<RpcResult<GetDpidFromInterfaceOutput>> output = interfaceMgrRpcService
+ .getDpidFromInterface(new GetDpidFromInterfaceInputBuilder().setIntfName(interfaceName).build());
+ try {
+ RpcResult<GetDpidFromInterfaceOutput> rpcResult = output.get();
+ if (rpcResult.isSuccessful()) {
+ dpId = rpcResult.getResult().getDpid();
+ }
+ } catch (NullPointerException | InterruptedException | ExecutionException e) {
+ logger.error("Failed to get the DPN ID: {} for interface {}: {} ", dpId, interfaceName, e);
+ }
+ return dpId;
+ }
+
+ /**
+ * Checks if is interface operational.
+ *
+ * @param interfaceName
+ * the interface name
+ * @param dataBroker
+ * the data broker
+ * @return true, if is interface operational
+ */
+ public static boolean isInterfaceOperational(String interfaceName, DataBroker dataBroker) {
+ if (StringUtils.isBlank(interfaceName)) {
+ return false;
+ }
+ Interface ifState = getInterfaceStateFromOperDS(interfaceName, dataBroker);
+ if (ifState == null) {
+ return false;
+ }
+ return ((ifState.getOperStatus() == OperStatus.Up) && (ifState.getAdminStatus() == AdminStatus.Up));
+ }
+
+ /**
+ * Gets the interface state from operational ds.
+ *
+ * @param interfaceName
+ * the interface name
+ * @param dataBroker
+ * the data broker
+ * @return the interface state from oper ds
+ */
+ public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceStateFromOperDS(
+ String interfaceName, DataBroker dataBroker) {
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId = createInterfaceStateInstanceIdentifier(
+ interfaceName);
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateOptional = MDSALUtil
+ .read(dataBroker, LogicalDatastoreType.OPERATIONAL, ifStateId);
+ if (ifStateOptional.isPresent()) {
+ return ifStateOptional.get();
+ }
+ return null;
+ }
+
+ /**
+ * Creates the interface state instance identifier.
+ *
+ * @param interfaceName
+ * the interface name
+ * @return the instance identifier
+ */
+ public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> createInterfaceStateInstanceIdentifier(
+ String interfaceName) {
+ InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> idBuilder = InstanceIdentifier
+ .builder(InterfacesState.class)
+ .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class,
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(
+ interfaceName));
+ return idBuilder.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.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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+
+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.setItmRpcService(rpcregistryDependency.getRpcService(ItmRpcService.class));
+ provider.setItmManager(getItmmanagerDependency());
+ provider.setIdManager(idManager);
+ provider.setEntityOwnershipService(getEntityOwnershipServiceDependency());
+ getBrokerDependency().registerProvider(provider);
+ return provider;
+ }
+
+}
--- /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.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>
+ <action class="org.opendaylight.vpnservice.elan.cli.l2gw.L2GwUtilsCacheCli">
+ </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 opendaylight-entity-ownership-service { prefix eos; revision-date 2015-08-10;}
+ 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;
+ }
+ }
+ }
+ container entity-ownership-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity eos:entity-ownership-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.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>elanmanager</artifactId>
+ <version>0.3.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>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>fcapsapplication-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-config</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>fcapsapplication-jmxapi</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.model</groupId>
+ <artifactId>model-flow-service</artifactId>
+ <version>${openflowplugin.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>openflowplugin-common</artifactId>
+ <version>${openflowplugin.version}</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ </plugin>
+
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifacts</id>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>${project.build.directory}/classes/initial/73-fcaps-app.xml</file>
+ <type>xml</type>
+ <classifier>config</classifier>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</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.vpnservice.fcapsapp;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.NotificationService;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.fcapsapp.performancecounter.FlowNodeConnectorInventoryTranslatorImpl;
+import org.opendaylight.vpnservice.fcapsapp.performancecounter.PMAgent;
+import org.opendaylight.vpnservice.fcapsapp.performancecounter.PacketInCounterHandler;
+import org.opendaylight.vpnservice.fcapsapp.portinfo.PortNameMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+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.vpnservice.fcapsapp.alarm.AlarmAgent;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FcapsProvider implements AutoCloseable {
+
+ public static Logger s_logger = LoggerFactory.getLogger(FcapsProvider.class);
+ private final DataBroker dataService;
+ private final NotificationService notificationProviderService;
+ private final EntityOwnershipService entityOwnershipService;
+ private FlowNodeConnectorInventoryTranslatorImpl flowNodeConnectorInventoryTranslatorImpl;
+ private PacketInCounterHandler packetInCounterHandler;
+ private NodeEventListener<FlowCapableNode> nodeNodeEventListener;
+ private final AlarmAgent alarmAgent;
+ private final PMAgent pmAgent;
+
+ /**
+ * Contructor sets the services
+ * @param dataBroker instance of databroker
+ * @param notificationService instance of notificationservice
+ * @param eos instance of EntityOwnershipService
+ */
+ public FcapsProvider(DataBroker dataBroker,NotificationService notificationService,
+ final EntityOwnershipService eos) {
+ this.dataService = Preconditions.checkNotNull(dataBroker, "DataBroker can not be null!");
+ s_logger.info("FcapsProvider dataBroket is set");
+
+ this.notificationProviderService = Preconditions.checkNotNull(notificationService,
+ "notificationService can not be null!");
+ s_logger.info("FcapsProvider notificationProviderService is set");
+
+ this.entityOwnershipService = Preconditions.checkNotNull(eos, "EntityOwnership service can not be null");
+ s_logger.info("FcapsProvider entityOwnershipService is set");
+
+ alarmAgent = new AlarmAgent();
+ pmAgent = new PMAgent();
+
+ alarmAgent.registerAlarmMbean();
+
+ pmAgent.registerMbeanForEFS();
+ pmAgent.registerMbeanForPorts();
+ pmAgent.registerMbeanForPacketIn();
+ PortNameMapping.registerPortMappingBean();
+
+ nodeNodeEventListener = new NodeEventListener<>(entityOwnershipService);
+ registerListener(dataService);
+ flowNodeConnectorInventoryTranslatorImpl = new
+ FlowNodeConnectorInventoryTranslatorImpl(dataService,entityOwnershipService);
+ packetInCounterHandler = new PacketInCounterHandler();
+ notificationProviderService.registerNotificationListener(packetInCounterHandler);
+ }
+
+ private void registerListener(DataBroker dataBroker) {
+ final DataTreeIdentifier<FlowCapableNode> treeId =
+ new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, getWildCardPath());
+ try {
+ dataBroker.registerDataTreeChangeListener(treeId, nodeNodeEventListener);
+ } catch (Exception e) {
+ s_logger.error("Registeration failed on DataTreeChangeListener {}",e);
+ }
+ }
+
+ private InstanceIdentifier<FlowCapableNode> getWildCardPath() {
+ return InstanceIdentifier.create(Nodes.class)
+ .child(Node.class)
+ .augmentation(FlowCapableNode.class);
+ }
+
+ @Override
+ public void close() throws Exception {
+
+ }
+}
--- /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.fcapsapp;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.md.sal.binding.api.*;
+
+import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipState;
+import org.opendaylight.vpnservice.fcapsapp.alarm.AlarmAgent;
+import org.opendaylight.vpnservice.fcapsapp.performancecounter.NodeUpdateCounter;
+import org.opendaylight.vpnservice.fcapsapp.performancecounter.PacketInCounterHandler;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.net.InetAddress;
+import java.util.Collection;
+
+public class NodeEventListener<D extends DataObject> implements ClusteredDataTreeChangeListener<D>,AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(NodeEventListener.class);
+ public static final AlarmAgent alarmAgent = new AlarmAgent();
+ public static final NodeUpdateCounter nodeUpdateCounter = new NodeUpdateCounter();
+ public static final PacketInCounterHandler packetInCounter = new PacketInCounterHandler();
+ private final EntityOwnershipService entityOwnershipService;
+
+ /**
+ * Construcor set EntityOwnershipService
+ * @param eos
+ */
+ public NodeEventListener(final EntityOwnershipService eos) {
+ this.entityOwnershipService = eos;
+ }
+
+ @Override
+ public void onDataTreeChanged(Collection<DataTreeModification<D>> changes) {
+ for (DataTreeModification<D> change : changes) {
+ final InstanceIdentifier<D> key = change.getRootPath().getRootIdentifier();
+ final DataObjectModification<D> mod = change.getRootNode();
+ final InstanceIdentifier<FlowCapableNode> nodeConnIdent =
+ key.firstIdentifierOf(FlowCapableNode.class);
+ String nodeId = null, hostName = null;
+ try {
+ nodeId = getDpnId(String.valueOf(nodeConnIdent.firstKeyOf(Node.class).getId()));
+ } catch (Exception ex) {
+ LOG.error("Dpn retrieval failed");
+ return;
+ }
+
+ hostName = System.getenv().get("HOSTNAME");
+ if (hostName == null) {
+ try {
+ hostName = InetAddress.getLocalHost().getHostName();
+ } catch (Exception e) {
+ LOG.error("Retrieving hostName failed {}", e);
+ }
+ }
+ LOG.debug("retrieved hostname {}", hostName);
+ if (nodeId != null) {
+ switch (mod.getModificationType()) {
+ case DELETE:
+ LOG.debug("NodeRemoved {} notification is received on host {}", nodeId, hostName);
+ if (nodeUpdateCounter.isDpnConnectedLocal(nodeId)) {
+ alarmAgent.raiseControlPathAlarm(nodeId, hostName);
+ nodeUpdateCounter.nodeRemovedNotification(nodeId, hostName);
+ }
+ packetInCounter.nodeRemovedNotification(nodeId);
+ break;
+ case SUBTREE_MODIFIED:
+ if (isNodeOwner(nodeId)) {
+ LOG.debug("NodeUpdated {} notification is received", nodeId);
+ } else {
+ LOG.debug("UPDATE: Node {} is not connected to host {}", nodeId, hostName);
+ }
+ break;
+ case WRITE:
+ if (mod.getDataBefore() == null) {
+ if (isNodeOwner(nodeId)) {
+ LOG.debug("NodeAdded {} notification is received on host {}", nodeId, hostName);
+ alarmAgent.clearControlPathAlarm(nodeId);
+ nodeUpdateCounter.nodeAddedNotification(nodeId, hostName);
+ } else {
+ LOG.debug("ADD: Node {} is not connected to host {}", nodeId, hostName);
+ }
+ }
+ break;
+ default:
+ LOG.debug("Unhandled Modification type {}", mod.getModificationType());
+ throw new IllegalArgumentException("Unhandled modification type " + mod.getModificationType());
+
+ }
+ } else {
+ LOG.error("DpnID is null");
+ }
+ }
+ }
+
+ private String getDpnId(String node) {
+ //Uri [_value=openflow:1]
+ String temp[] = node.split("=");
+ String dpnId = temp[1].substring(0,temp[1].length() - 1);
+ return dpnId;
+
+ }
+
+ /**
+ * Method checks if *this* instance of controller is owner of
+ * the given openflow node.
+ * @param nodeId DpnId
+ * @return True if owner, else false
+ */
+ public boolean isNodeOwner(String nodeId) {
+ Entity entity = new Entity("openflow", nodeId);
+ Optional<EntityOwnershipState> entityState = this.entityOwnershipService.getOwnershipState(entity);
+ if (entityState.isPresent()) {
+ return entityState.get().isOwner();
+ }
+ return false;
+ }
+
+ @Override
+ public void close() throws Exception {
+ }
+}
\ 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.fcapsapp.alarm;
+
+import org.opendaylight.vpnservice.fcapsappjmx.ControlPathFailureAlarm;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import java.lang.management.ManagementFactory;
+
+public class AlarmAgent {
+ static Logger s_logger = LoggerFactory.getLogger(AlarmAgent.class);
+ private MBeanServer mbs = null;
+ private ObjectName alarmName = null;
+ private static final String BEANNAME = "SDNC.FM:name=ControlPathFailureAlarmBean";
+ private static ControlPathFailureAlarm alarmBean = new ControlPathFailureAlarm();
+
+ /**
+ * constructor get the instance of platform MBeanServer
+ */
+ public AlarmAgent() {
+ mbs = ManagementFactory.getPlatformMBeanServer();
+ try {
+ alarmName = new ObjectName(BEANNAME);
+ } catch (MalformedObjectNameException e) {
+ s_logger.error("ObjectName instance creation failed for BEANAME {} : {}",BEANNAME, e);
+ }
+ }
+
+ /**
+ * Method registers alarm mbean in platform MbeanServer
+ */
+ public void registerAlarmMbean() {
+ try {
+ if (!mbs.isRegistered(alarmName)) {
+ mbs.registerMBean(alarmBean, alarmName);
+ s_logger.info("Registered Mbean {} successfully", alarmName);
+ }
+ } catch (Exception e) {
+ s_logger.error("Registeration failed for Mbean {} :{}", alarmName,e);
+ }
+ }
+
+ /**
+ * Method invoke raise alarm JMX API in platform MbeanServer with alarm details
+ * @param alarmId
+ * alarm to be raised
+ * @param text
+ * Additional details describing about the alarm on which dpnId and hostname
+ * @param src
+ * Source of the alarm ex: dpnId=openflow:1
+ * the source node that caused this alarm
+ */
+ public void invokeFMraisemethod(String alarmId,String text,String src) {
+ try {
+ mbs.invoke(alarmName, "raiseAlarm", new Object[]{alarmId, text, src},
+ new String[]{String.class.getName(), String.class.getName(), String.class.getName()});
+ s_logger.debug("Invoked raiseAlarm function for Mbean {} with source {}", BEANNAME, src);
+ } catch (Exception e) {
+ s_logger.error("Invoking raiseAlarm method failed for Mbean {} :{}", alarmName,e);
+ }
+ }
+
+ /**
+ * Method invoke clear alarm JMX API in platform MbeanServer with alarm details
+ * @param alarmId
+ * alarm to be cleared
+ * @param text
+ * Additional details describing about the alarm on which dpnId and hostname
+ * @param src
+ * Source of the alarm ex: dpn=openflow:1
+ * the source node that caused this alarm
+ */
+ public void invokeFMclearmethod(String alarmId,String text,String src) {
+ try {
+ mbs.invoke(alarmName, "clearAlarm", new Object[]{alarmId, text, src},
+ new String[]{String.class.getName(), String.class.getName(), String.class.getName()});
+ s_logger.debug("Invoked clearAlarm function for Mbean {} with source {}",BEANNAME,src);
+ } catch (Exception e) {
+ s_logger.error("Invoking clearAlarm method failed for Mbean {} :{}", alarmName,e);
+ }
+ }
+
+ /**
+ * Method gets the alarm details to be raised and construct the alarm objects
+ * @param nodeId
+ * Source of the alarm dpnId
+ * @param host
+ * Controller hostname
+ */
+ public void raiseControlPathAlarm(String nodeId,String host) {
+ StringBuilder alarmText = new StringBuilder();
+ StringBuilder source = new StringBuilder();
+
+ if (host != null) {
+ try {
+ alarmText.append("OF Switch ").append(nodeId).append(" lost heart beat communication with controller ")
+ .append(host);
+ source.append("Dpn=").append(nodeId);
+
+ s_logger.debug("Raising ControlPathConnectionFailure alarm... alarmText {} source {} ", alarmText, source);
+ //Invokes JMX raiseAlarm method
+ invokeFMraisemethod("ControlPathConnectionFailure", alarmText.toString(), source.toString());
+ } catch (Exception e) {
+ s_logger.error("Exception before invoking raise method in jmx {}", e);
+ }
+ } else {
+ s_logger.error("Received hostname is null");
+ }
+ }
+
+ /**
+ * Method gets the alarm details to be cleared and construct the alarm objects
+ * @param nodeId
+ * Source of the alarm dpnId
+ */
+ public void clearControlPathAlarm(String nodeId) {
+ StringBuilder source = new StringBuilder();
+
+ try {
+ source.append("Dpn=").append(nodeId);
+ s_logger.debug("Clearing ControlPathConnectionFailure alarm of source {} ", source);
+ //Invokes JMX clearAlarm method
+ invokeFMclearmethod("ControlPathConnectionFailure", "OF Switch gained communication with controller",
+ source.toString());
+ } catch (Exception e) {
+ s_logger.error("Exception before invoking clear method jmx {}", e);
+ }
+ }
+}
\ 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.fcapsapp.performancecounter;
+
+import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public interface FlowCapableNodeConnectorCommitter <D extends DataObject> extends AutoCloseable, ClusteredDataTreeChangeListener<D> {
+ /**
+ * Method removes DataObject which is identified by InstanceIdentifier
+ * from device.
+ *
+ * @param identifier - the whole path to DataObject
+ * @param del - DataObject for removing
+ * @param nodeConnIdent NodeConnector InstanceIdentifier
+ */
+ void remove(InstanceIdentifier<D> identifier, D del,
+ InstanceIdentifier<FlowCapableNodeConnector> nodeConnIdent);
+
+ /**
+ * Method updates the original DataObject to the update DataObject
+ * in device. Both are identified by same InstanceIdentifier
+ *
+ * @param identifier - the whole path to DataObject
+ * @param original - original DataObject (for update)
+ * @param update - changed DataObject (contain updates)
+ * @param nodeConnIdent NodeConnector InstanceIdentifier
+ */
+ void update(InstanceIdentifier<D> identifier, D original, D update,
+ InstanceIdentifier<FlowCapableNodeConnector> nodeConnIdent);
+
+ /**
+ * Method adds the DataObject which is identified by InstanceIdentifier
+ * to device.
+ *
+ * @param identifier - the whole path to new DataObject
+ * @param add - new DataObject
+ * @param nodeConnIdent NodeConnector InstanceIdentifier
+ */
+ void add(InstanceIdentifier<D> identifier, D add,
+ InstanceIdentifier<FlowCapableNodeConnector> nodeConnIdent);
+
+}
+
--- /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.fcapsapp.performancecounter;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.*;
+import org.opendaylight.controller.md.sal.binding.api.*;
+import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipState;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.openflowplugin.common.wait.SimpleTaskRetryLooper;
+import org.opendaylight.vpnservice.fcapsapp.portinfo.PortNameMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+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.lang.String;
+import java.util.HashMap;
+import java.util.Collection;
+import java.util.concurrent.Callable;
+
+public class FlowNodeConnectorInventoryTranslatorImpl extends NodeConnectorEventListener<FlowCapableNodeConnector> {
+ public static final int STARTUP_LOOP_TICK = 500;
+ public static final int STARTUP_LOOP_MAX_RETRIES = 8;
+ private static final Logger LOG = LoggerFactory.getLogger(FlowNodeConnectorInventoryTranslatorImpl.class);
+ private final EntityOwnershipService entityOwnershipService;
+
+ private ListenerRegistration<FlowNodeConnectorInventoryTranslatorImpl> dataTreeChangeListenerRegistration;
+
+ public static final String SEPARATOR = ":";
+ private static final PMAgent pmAgent = new PMAgent();
+
+ private static final InstanceIdentifier<FlowCapableNodeConnector> II_TO_FLOW_CAPABLE_NODE_CONNECTOR
+ = InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class)
+ .child(NodeConnector.class)
+ .augmentation(FlowCapableNodeConnector.class)
+ .build();
+
+ private static Multimap<Long,String> dpnToPortMultiMap = Multimaps.synchronizedListMultimap(ArrayListMultimap.<Long,String>create());
+
+ private static HashMap<String, String> nodeConnectorCountermap = new HashMap<String, String>();
+
+ public FlowNodeConnectorInventoryTranslatorImpl(final DataBroker dataBroker,final EntityOwnershipService eos) {
+ super( FlowCapableNodeConnector.class);
+ Preconditions.checkNotNull(dataBroker, "DataBroker can not be null!");
+
+ entityOwnershipService = eos;
+ final DataTreeIdentifier<FlowCapableNodeConnector> treeId =
+ new DataTreeIdentifier<>(LogicalDatastoreType.OPERATIONAL, getWildCardPath());
+ try {
+ SimpleTaskRetryLooper looper = new SimpleTaskRetryLooper(STARTUP_LOOP_TICK,
+ STARTUP_LOOP_MAX_RETRIES);
+ dataTreeChangeListenerRegistration = looper.loopUntilNoException(new Callable<ListenerRegistration<FlowNodeConnectorInventoryTranslatorImpl>>() {
+ @Override
+ public ListenerRegistration<FlowNodeConnectorInventoryTranslatorImpl> call() throws Exception {
+ return dataBroker.registerDataTreeChangeListener(treeId, FlowNodeConnectorInventoryTranslatorImpl.this);
+ }
+ });
+ } catch (final Exception e) {
+ LOG.warn(" FlowNodeConnectorInventoryTranslatorImpl listener registration fail!");
+ LOG.debug("FlowNodeConnectorInventoryTranslatorImpl DataChange listener registration fail ..", e);
+ throw new IllegalStateException("FlowNodeConnectorInventoryTranslatorImpl startup fail! System needs restart.", e);
+ }
+ }
+
+
+ protected InstanceIdentifier<FlowCapableNodeConnector> getWildCardPath() {
+ return InstanceIdentifier.create(Nodes.class)
+ .child(Node.class)
+ .child(NodeConnector.class)
+ .augmentation(FlowCapableNodeConnector.class);
+ }
+
+ @Override
+ public void close() {
+ if (dataTreeChangeListenerRegistration != null) {
+ try {
+ dataTreeChangeListenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.warn("Error by stop FRM FlowNodeConnectorInventoryTranslatorImpl: {}", e.getMessage());
+ LOG.debug("Error by stop FRM FlowNodeConnectorInventoryTranslatorImpl..", e);
+ }
+ dataTreeChangeListenerRegistration = null;
+ }
+ }
+ @Override
+ public void remove(InstanceIdentifier<FlowCapableNodeConnector> identifier, FlowCapableNodeConnector del, InstanceIdentifier<FlowCapableNodeConnector> nodeConnIdent) {
+ if(compareInstanceIdentifierTail(identifier,II_TO_FLOW_CAPABLE_NODE_CONNECTOR)) {
+ String sNodeConnectorIdentifier = getNodeConnectorId(String.valueOf(nodeConnIdent.firstKeyOf(NodeConnector.class).getId()));
+ long nDpId = getDpIdFromPortName(sNodeConnectorIdentifier);
+ if (dpnToPortMultiMap.containsKey(nDpId)) {
+ LOG.debug("Node Connector {} removed", sNodeConnectorIdentifier);
+ dpnToPortMultiMap.remove(nDpId, sNodeConnectorIdentifier);
+ sendNodeConnectorUpdation(nDpId);
+ PortNameMapping.updatePortMap("openflow:" + nDpId + ":" + del.getName(), sNodeConnectorIdentifier, "DELETE");
+ }
+ }
+ }
+
+ @Override
+ public void update(InstanceIdentifier<FlowCapableNodeConnector> identifier, FlowCapableNodeConnector original, FlowCapableNodeConnector update, InstanceIdentifier<FlowCapableNodeConnector> nodeConnIdent) {
+ if(compareInstanceIdentifierTail(identifier,II_TO_FLOW_CAPABLE_NODE_CONNECTOR)) {
+
+ //donot need to do anything as we are not considering updates here
+ String sNodeConnectorIdentifier = getNodeConnectorId(String.valueOf(nodeConnIdent.firstKeyOf(NodeConnector.class).getId()));
+ long nDpId = getDpIdFromPortName(sNodeConnectorIdentifier);
+ if (isNodeOwner(getNodeId(nDpId))) {
+ boolean original_portstatus = original.getConfiguration().isPORTDOWN();
+ boolean update_portstatus = update.getConfiguration().isPORTDOWN();
+
+ if (update_portstatus == true) {
+ //port has gone down
+ LOG.debug("Node Connector {} updated port is down", sNodeConnectorIdentifier);
+ } else if (original_portstatus == true) {
+ //port has come up
+ LOG.debug("Node Connector {} updated port is up", sNodeConnectorIdentifier);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void add(InstanceIdentifier<FlowCapableNodeConnector> identifier, FlowCapableNodeConnector add, InstanceIdentifier<FlowCapableNodeConnector> nodeConnIdent) {
+ if (compareInstanceIdentifierTail(identifier,II_TO_FLOW_CAPABLE_NODE_CONNECTOR)){
+
+ String sNodeConnectorIdentifier = getNodeConnectorId(String.valueOf(nodeConnIdent.firstKeyOf(NodeConnector.class).getId()));
+ long nDpId = getDpIdFromPortName(sNodeConnectorIdentifier);
+ if (isNodeOwner(getNodeId(nDpId))) {
+ if (!dpnToPortMultiMap.containsEntry(nDpId, sNodeConnectorIdentifier)) {
+ LOG.debug("Node Connector {} added", sNodeConnectorIdentifier);
+ dpnToPortMultiMap.put(nDpId, sNodeConnectorIdentifier);
+ sendNodeConnectorUpdation(nDpId);
+ PortNameMapping.updatePortMap("openflow:" + nDpId + ":" + add.getName(), sNodeConnectorIdentifier, "ADD");
+ } else {
+ LOG.error("Duplicate Event.Node Connector already added");
+ }
+ }
+ }
+ }
+ private String getNodeConnectorId(String node) {
+ //Uri [_value=openflow:1:1]
+ String temp[] = node.split("=");
+ String dpnId = temp[1].substring(0,temp[1].length() - 1);
+ return dpnId;
+ }
+
+ private String getNodeId(Long dpnId){
+ return "openflow:" + dpnId;
+ }
+ /**
+ * Method checks if *this* instance of controller is owner of
+ * the given openflow node.
+ * @param nodeId openflow node Id
+ * @return True if owner, else false
+ */
+ public boolean isNodeOwner(String nodeId) {
+ Entity entity = new Entity("openflow", nodeId);
+ Optional<EntityOwnershipState> eState = this.entityOwnershipService.getOwnershipState(entity);
+ if(eState.isPresent()) {
+ return eState.get().isOwner();
+ }
+ return false;
+ }
+
+ private boolean compareInstanceIdentifierTail(InstanceIdentifier<?> identifier1,
+ InstanceIdentifier<?> identifier2) {
+ return Iterables.getLast(identifier1.getPathArguments()).equals(Iterables.getLast(identifier2.getPathArguments()));
+ }
+
+ private long getDpIdFromPortName(String portName) {
+ String dpId = portName.substring(portName.indexOf(SEPARATOR) + 1, portName.lastIndexOf(SEPARATOR));
+ return Long.parseLong(dpId);
+ }
+
+ private void sendNodeConnectorUpdation(Long dpnId) {
+ Collection<String> portname = dpnToPortMultiMap.get(dpnId);
+ String nodeListPortsCountStr,counterkey;
+ nodeListPortsCountStr = "dpnId_" + dpnId + "_NumberOfOFPorts";
+ counterkey = "NumberOfOFPorts:" + nodeListPortsCountStr;
+
+ if (portname.size()!=0) {
+ nodeConnectorCountermap.put(counterkey, "" + portname.size());
+ } else {
+ nodeConnectorCountermap.remove(counterkey);
+ }
+ LOG.debug("NumberOfOFPorts:" + nodeListPortsCountStr + " portlistsize " + portname.size());
+ pmAgent.connectToPMAgentForNOOfPorts(nodeConnectorCountermap);
+ }
+}
\ 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.fcapsapp.performancecounter;
+
+import org.opendaylight.controller.md.sal.binding.api.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import java.util.Collection;
+
+public abstract class NodeConnectorEventListener <T extends DataObject> implements ClusteredDataTreeChangeListener<T>,AutoCloseable,FlowCapableNodeConnectorCommitter<T> {
+ NodeConnectorEventListener(Class<FlowCapableNodeConnector> flowCapableNodeConnectorClass) {
+ }
+
+ @Override
+ public void onDataTreeChanged(Collection<DataTreeModification<T>> changes) {
+ for (DataTreeModification<T> change : changes) {
+ final InstanceIdentifier<T> key = change.getRootPath().getRootIdentifier();
+ final DataObjectModification<T> mod = change.getRootNode();
+ final InstanceIdentifier<FlowCapableNodeConnector> nodeConnIdent =
+ key.firstIdentifierOf(FlowCapableNodeConnector.class);
+
+ switch (mod.getModificationType()) {
+ case DELETE:
+ remove(key, mod.getDataBefore(), nodeConnIdent);
+ break;
+ case SUBTREE_MODIFIED:
+ update(key, mod.getDataBefore(), mod.getDataAfter(), nodeConnIdent);
+ break;
+ case WRITE:
+ if (mod.getDataBefore() == null) {
+ add(key, mod.getDataAfter(), nodeConnIdent);
+ } else {
+ update(key, mod.getDataBefore(), mod.getDataAfter(), nodeConnIdent);
+ }
+ break;
+
+
+ default:
+ throw new IllegalArgumentException("Unhandled modification type " + mod.getModificationType());
+ }
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ }
+}
--- /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.fcapsapp.performancecounter;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.lang.Integer;
+import java.lang.String;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+public class NodeUpdateCounter {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NodeUpdateCounter.class);
+ private String nodeListEFSCountStr;
+ private static HashSet<String> dpnList = new HashSet<String>();
+ public static final PMAgent pmagent = new PMAgent();
+ Map<String, String> counter_map = new HashMap<String, String>();
+
+ public NodeUpdateCounter() {
+ }
+
+ public void nodeAddedNotification(String sNode,String hostName) {
+ dpnList.add(sNode);
+ sendNodeUpdation(dpnList.size(),hostName);
+ }
+
+ public void nodeRemovedNotification(String sNode,String hostName) {
+ dpnList.remove(sNode);
+ sendNodeUpdation(dpnList.size(), hostName);
+ }
+
+ private void sendNodeUpdation(Integer count,String hostName) {
+
+ if (hostName != null) {
+ nodeListEFSCountStr = "Node_" + hostName + "_NumberOfEFS";
+ LOG.debug("NumberOfEFS:" + nodeListEFSCountStr + " dpnList.size " + count);
+
+ counter_map.put("NumberOfEFS:" + nodeListEFSCountStr, "" + count);
+ pmagent.connectToPMAgent(counter_map);
+ } else
+ LOG.error("Hostname is null upon NumberOfEFS counter");
+ }
+
+ public boolean isDpnConnectedLocal(String sNode) {
+ if (dpnList.contains(sNode))
+ return true;
+ return false;
+ }
+}
\ 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.fcapsapp.performancecounter;
+
+
+import org.opendaylight.vpnservice.fcapsappjmx.NumberOfOFPorts;
+import org.opendaylight.vpnservice.fcapsappjmx.NumberOfOFSwitchCounter;
+import org.opendaylight.vpnservice.fcapsappjmx.PacketInCounter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.management.*;
+import java.lang.String;
+import java.lang.management.ManagementFactory;
+import java.util.Map;
+
+public class PMAgent {
+ private static Logger s_logger = LoggerFactory.getLogger(PMAgent.class);
+ private MBeanServer mbs = null;
+ private ObjectName switch_mbeanName = null;
+ private ObjectName port_mbeanName = null;
+ private ObjectName pktIn_mbeanName = null;
+ private static final String SWITCH_BEANNAME = "SDNC.PM:type=NumberOfOFSwitchCounter";
+ private static final String PORTS_BEANNAME = "SDNC.PM:type=NumberOfOFPortsCounter";
+ private static final String PKTIN_BEANNAME = "SDNC.PM:type=InjectedPacketInCounter";
+
+ private static NumberOfOFSwitchCounter switchCounterBean = new NumberOfOFSwitchCounter();
+ private static NumberOfOFPorts PortcounterBean = new NumberOfOFPorts();
+ private static PacketInCounter packetInCounter = new PacketInCounter();
+
+ public PMAgent() {
+ mbs = ManagementFactory.getPlatformMBeanServer();
+ try {
+ switch_mbeanName = new ObjectName(SWITCH_BEANNAME);
+ port_mbeanName = new ObjectName(PORTS_BEANNAME);
+ pktIn_mbeanName = new ObjectName(PKTIN_BEANNAME);
+ } catch (MalformedObjectNameException e) {
+ s_logger.error("ObjectName instance creation failed for BEANAME {}", e);
+
+ }
+ }
+
+ public void registerMbeanForEFS() {
+ try {
+ if (!mbs.isRegistered(switch_mbeanName)) {
+ mbs.registerMBean(switchCounterBean, switch_mbeanName);
+ s_logger.info("Registered Mbean {} successfully", switch_mbeanName);
+ }
+
+ } catch (Exception e) {
+ s_logger.error("Registeration failed for Mbean {} :{}", switch_mbeanName, e);
+ }
+ }
+
+ public void registerMbeanForPorts() {
+ try {
+ if (!mbs.isRegistered(port_mbeanName)) {
+ mbs.registerMBean(PortcounterBean, port_mbeanName);
+ s_logger.info("Registered Mbean {} successfully", port_mbeanName);
+ }
+ } catch (Exception e) {
+ s_logger.error("Registeration failed for Mbean {} :{}", port_mbeanName, e);
+ }
+ }
+
+ public void registerMbeanForPacketIn() {
+ try {
+ if (!mbs.isRegistered(pktIn_mbeanName)) {
+ mbs.registerMBean(packetInCounter,pktIn_mbeanName);
+ s_logger.info("Registered Mbean {} successfully",pktIn_mbeanName );
+ }
+ } catch (Exception e) {
+ s_logger.error("Registeration failed for Mbean {} :{}",pktIn_mbeanName , e);
+ }
+ }
+
+ public void connectToPMAgent(Map map) {
+ switchCounterBean.updateCounter(map);
+ }
+
+ public void connectToPMAgentForNOOfPorts(Map map) {
+ PortcounterBean.updateCounter(map);
+ }
+
+ public void sendPacketInCounterUpdate(Map map){
+ packetInCounter.updateCounter(map);
+ }
+}
--- /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.fcapsapp.performancecounter;
+
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class PacketInCounterHandler implements PacketProcessingListener {
+ private static final Logger LOG = LoggerFactory.getLogger(PacketInCounterHandler.class);
+ private static ConcurrentHashMap<String,AtomicLong> ingressPacketMap = new ConcurrentHashMap<>();
+ private static HashMap<String,String> packetInMap = new HashMap<>();
+ private static final Integer FIRST_VALUE = 1;
+ private static final PMAgent pmAgent =new PMAgent();
+
+ @Override
+ public void onPacketReceived(PacketReceived notification) {
+ String dpnId = null;
+ String nodeListEgressStr, nodekey;
+ LOG.debug("Ingress packet notification received");
+ try {
+ if (notification.getIngress() == null) {
+ if (LOG.isWarnEnabled()) {
+ LOG.warn("invalid PacketReceived notification");
+ }
+ return;
+ }
+ dpnId = getDpnId(notification.getIngress().getValue().toString());
+ } catch (Exception e) {
+ if (LOG.isWarnEnabled()) {
+ LOG.warn("DPN Parsing failed in onPacketReceived");
+ }
+ }
+ if (dpnId != null) {
+ nodeListEgressStr = "dpnId_" + dpnId + "_InjectedOFMessagesSent";
+ nodekey = "InjectedOFMessagesSent:" + nodeListEgressStr;
+ if (ingressPacketMap.containsKey(dpnId)) {
+ ingressPacketMap.put(dpnId,new AtomicLong(ingressPacketMap.get(dpnId).incrementAndGet()));
+ packetInMap.put(nodekey,""+ingressPacketMap.get(dpnId));
+ } else {
+ ingressPacketMap.put(dpnId, new AtomicLong(FIRST_VALUE));
+ packetInMap.put(nodekey,""+FIRST_VALUE);
+ }
+ connectToPMAgent();
+ } else {
+ LOG.error("DpnId is null");
+ }
+ }
+ private void connectToPMAgent(){
+ pmAgent.sendPacketInCounterUpdate(packetInMap);
+ }
+ /*
+ * Method to extract DpnId
+ */
+ public static String getDpnId(String id) {
+ String[] nodeNo = id.split(":");
+ String[] dpnId = nodeNo[1].split("]");
+ return dpnId[0];
+ }
+
+ public void nodeRemovedNotification(String dpnId){
+ String nodeListEgressStr, nodekey;
+ if (dpnId != null) {
+ dpnId = dpnId.split(":")[1];
+ LOG.debug("Dpnvalue Id {}",dpnId);
+ if (ingressPacketMap.containsKey(dpnId)) {
+ nodeListEgressStr = "dpnId_" + dpnId + "_InjectedOFMessagesSent";
+ nodekey = "InjectedOFMessagesSent:" + nodeListEgressStr;
+ synchronized (this) {
+ ingressPacketMap.remove(dpnId);
+ packetInMap.remove(nodekey);
+ connectToPMAgent();
+ }
+ LOG.debug("Node {} Removed for PacketIn counter", dpnId);
+ }
+ } else {
+ LOG.error("DpnId is null upon nodeRemovedNotification");
+ }
+ }
+}
\ 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.fcapsapp.portinfo;
+
+import java.lang.String;
+import java.util.HashMap;
+import java.util.Map;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import javax.management.*;
+import java.lang.management.ManagementFactory;
+
+public class PortNameMapping implements PortNameMappingMBean {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PortNameMapping.class);
+
+ private static Map<String,String> portNameToPortIdMap = new HashMap<String,String>();
+
+ @Override
+ public Map<String,String> getPortIdtoPortNameMap() {
+ return portNameToPortIdMap;
+ }
+
+ @Override
+ public String getPortName(String portId){
+ return portNameToPortIdMap.get(portId);
+ }
+
+ public static void updatePortMap(String portName,String portId,String status) {
+ if (status.equals("ADD")){
+ portNameToPortIdMap.put(portId,portName);
+ LOG.debug("PortId {} : portName {} added",portId,portName);
+ } else if(status.equals("DELETE")){
+ portNameToPortIdMap.remove(portId);
+ LOG.debug("PortId {} : portName {} removed",portId,portName);
+ }
+ }
+
+ public static void registerPortMappingBean() {
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ ObjectName mbeanName = null;
+ String BEANNAME = "Ports:type=PortNameMapping";
+
+ try {
+ mbeanName = new ObjectName(BEANNAME);
+ } catch (MalformedObjectNameException e) {
+ LOG.error("ObjectName instance creation failed for BEANAME {} : {}", BEANNAME, e);
+
+ }
+ try {
+ if (!mbs.isRegistered(mbeanName)) {
+ mbs.registerMBean(new PortNameMapping(), mbeanName);
+ LOG.debug("Registered Mbean {} successfully", mbeanName);
+ }
+
+ } catch (Exception e) {
+ LOG.error("Registeration failed for Mbean {} :{}", mbeanName, e);
+ }
+ }
+}
\ 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.fcapsapp.portinfo;
+
+import java.lang.String;
+import java.util.Map;
+
+public interface PortNameMappingMBean {
+ public Map<String,String> getPortIdtoPortNameMap();
+ public String getPortName(String portId);
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.fcaps.app.rev151211;
+
+import org.opendaylight.vpnservice.fcapsapp.FcapsProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FcapsAppModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.fcaps.app.rev151211.AbstractFcapsAppModule {
+ private static final Logger LOG = LoggerFactory.getLogger(FcapsAppModule.class);
+ public FcapsAppModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public FcapsAppModule(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.openflowplugin.app.fcaps.app.rev151211.FcapsAppModule 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() {
+ LOG.info("Fcaps module initialization");
+ return new FcapsProvider(getDataBrokerDependency(),getNotificationAdapterDependency(),getEntityOwnershipServiceDependency());
+ }
+
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: fcaps-app yang module local name: fcaps-app
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Fri Feb 05 20:19:50 IST 2016
+*
+* 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.openflowplugin.app.fcaps.app.rev151211;
+public class FcapsAppModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.app.fcaps.app.rev151211.AbstractFcapsAppModuleFactory {
+
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2015 Cisco Systems, Inc. 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>
+ <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:fcaps="urn:opendaylight:params:xml:ns:yang:openflowplugin:app:fcaps-app">
+ fcaps:fcaps-app
+ </type>
+ <name>fcaps-app</name>
+
+ <data-broker>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
+ <name>pingpong-binding-data-broker</name>
+ </data-broker>
+ <rpc-registry>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+ <name>binding-rpc-broker</name>
+ </rpc-registry>
+ <notification-adapter>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">binding:binding-new-notification-service</type>
+ <name>binding-notification-adapter</name>
+ </notification-adapter>
+ <entity-ownership-service>
+ <type xmlns:entity-ownership="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:entity-ownership-service">entity-ownership:entity-ownership-service</type>
+ <name>entity-ownership-service</name>
+ </entity-ownership-service>
+ </module>
+ </modules>
+ </data>
+ </configuration>
+
+ <required-capabilities>
+ <capability>
+ urn:opendaylight:params:xml:ns:yang:openflowplugin:app:fcaps-app?module=fcaps-app&revision=2015-12-11
+ </capability>
+ <capability>
+ urn:opendaylight:params:xml:ns:yang:controller:config:distributed-entity-ownership-service?module=distributed-entity-ownership-service&revision=2015-08-10
+ </capability>
+ </required-capabilities>
+
+</snapshot>
--- /dev/null
+module fcaps-app {
+
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:openflowplugin:app:fcaps-app";
+ prefix "fcaps";
+
+ 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 sal-broker; revision-date 2013-10-28;}
+ import opendaylight-entity-ownership-service { prefix eos; }
+
+ description
+ "This module contains the base YANG definitions for
+ fcaps-manager implementation.";
+
+ revision "2015-12-11" {
+ description
+ "Initial revision.";
+ }
+
+ identity fcaps-app {
+ base config:module-type;
+ config:java-name-prefix FcapsApp;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case fcaps-app {
+ when "/config:modules/config:module/config:type = 'fcaps-app'";
+
+ container data-broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-async-data-broker;
+ }
+ }
+ }
+ container rpc-registry {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-rpc-registry;
+ }
+ }
+ }
+ container notification-adapter {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity sal-broker:binding-new-notification-service;
+ }
+ }
+ }
+ container entity-ownership-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity eos:entity-ownership-service;
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>fcapsapplication-jmxapi</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+
+</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.vpnservice.fcapsappjmx;
+
+import javax.management.AttributeChangeNotification;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import java.util.ArrayList;
+
+public class ControlPathFailureAlarm extends NotificationBroadcasterSupport implements ControlPathFailureAlarmMBean {
+
+ ArrayList<String> raiseAlarmObject = new ArrayList<String>();
+ ArrayList<String> clearAlarmObject = new ArrayList<String>();
+ private long sequenceNumber = 1;
+
+ public void setRaiseAlarmObject(ArrayList<String> raiseAlarmObject) {
+ this.raiseAlarmObject = raiseAlarmObject;
+
+ Notification notif = new AttributeChangeNotification(this,
+ sequenceNumber++, System.currentTimeMillis(),
+ "raise alarm object notified ", "raiseAlarmObject", "ArrayList",
+ "", this.raiseAlarmObject);
+ sendNotification(notif);
+ }
+
+ public ArrayList<String> getRaiseAlarmObject() {
+ return raiseAlarmObject;
+ }
+
+ public void setClearAlarmObject(ArrayList<String> clearAlarmObject) {
+ this.clearAlarmObject = clearAlarmObject;
+
+ Notification notif = new AttributeChangeNotification(this,
+ sequenceNumber++, System.currentTimeMillis(),
+ "clear alarm object notified ", "clearAlarmObject", "ArrayList",
+ "", this.clearAlarmObject);
+ sendNotification(notif);
+ }
+
+ public ArrayList<String> getClearAlarmObject() {
+ return clearAlarmObject;
+ }
+
+ public synchronized void raiseAlarm(String alarmName, String additionalText, String source) {
+ raiseAlarmObject.add(alarmName);
+ raiseAlarmObject.add(additionalText);
+ raiseAlarmObject.add(source);
+ setRaiseAlarmObject(raiseAlarmObject);
+ raiseAlarmObject.clear();
+ }
+
+ public synchronized void clearAlarm(String alarmName, String additionalText, String source) {
+ clearAlarmObject.add(alarmName);
+ clearAlarmObject.add(additionalText);
+ clearAlarmObject.add(source);
+ setClearAlarmObject(clearAlarmObject);
+ clearAlarmObject.clear();
+ }
+}
--- /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.fcapsappjmx;
+
+import java.util.ArrayList;
+
+public interface ControlPathFailureAlarmMBean {
+ public void setRaiseAlarmObject(ArrayList<String> raiseAlarmObject);
+ public ArrayList<String> getRaiseAlarmObject();
+ public void setClearAlarmObject(ArrayList<String> clearAlarmObject);
+ public ArrayList<String> getClearAlarmObject();
+ public void raiseAlarm(String alarmName, String additionalText, String source);
+ public void clearAlarm(String alarmName, String additionalText, String source);
+}
--- /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.fcapsappjmx;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class NumberOfOFPorts implements NumberOfOFPortsMBean {
+ private static Map<String,String> counterCache = new HashMap<String,String>();
+
+ @Override
+ public void updateCounter(Map<String, String> map) {
+ counterCache = map;
+ }
+
+ @Override
+ public Map<String, String> retrieveCounterMap() {
+ return counterCache;
+ }
+}
--- /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.fcapsappjmx;
+
+import java.util.Map;
+
+public interface NumberOfOFPortsMBean {
+ //-----------
+ // operations
+ //-----------
+ public void updateCounter(Map<String, String> map);
+ public Map<String, String> retrieveCounterMap();
+}
--- /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.fcapsappjmx;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class NumberOfOFSwitchCounter implements NumberOfOFSwitchCounterMBean {
+ private static Map<String,String> counterCache = new HashMap<String,String>();
+
+ @Override
+ public void updateCounter(Map<String, String> map) {
+ counterCache = map;
+ }
+
+ @Override
+ public Map<String, String> retrieveCounterMap() {
+ return counterCache;
+ }
+}
--- /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.fcapsappjmx;
+
+import java.util.Map;
+
+public interface NumberOfOFSwitchCounterMBean {
+ //-----------
+ // operations
+ //-----------
+ public void updateCounter(Map<String, String> map);
+ public Map<String, String> retrieveCounterMap();
+}
--- /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.fcapsappjmx;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class PacketInCounter implements PacketInCounterMBean {
+ private static Map<String,String> counterCache = new HashMap<String,String>();
+
+ @Override
+ public void updateCounter(Map<String, String> map) {
+ counterCache = map;
+ }
+
+ @Override
+ public Map<String, String> retrieveCounterMap() {
+ return counterCache;
+ }
+}
--- /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.fcapsappjmx;
+
+import java.util.Map;
+
+public interface PacketInCounterMBean {
+ //-----------
+ // operations
+ //-----------
+ public void updateCounter(Map<String, String> map);
+ public Map<String, String> retrieveCounterMap();
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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,
+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.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>fcapsapplication</artifactId>
+ <version>0.2.1-SNAPSHOT</version>
+ <name>fcapsapplication</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>fcapsapplication-jmxapi</module>
+ <module>fcapsapplication-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>
\ 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) 2015 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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>alarmmanager</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <maven-bundle-plugin.version>2.5.3</maven-bundle-plugin.version>
+ <osgi.version>5.0.0</osgi.version>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>${osgi.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>fcaps-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven-bundle-plugin.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+ <Bundle-Version>${project.version}</Bundle-Version>
+ <Bundle-Activator>org.opendaylight.vpnservice.fcapsmanager.alarmmanager.Activator</Bundle-Activator>
+ <Export-Package>org.opendaylight.vpnservice.fcapsmanager.alarmmanager*;version=${project.version}</Export-Package>
+ <Import-Package>*</Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
\ 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.fcapsmanager.alarmmanager;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Activator implements BundleActivator {
+ static Logger s_logger = LoggerFactory.getLogger(Activator.class);
+ private Runnable listener;
+ private Thread listenerThread;
+
+ public void start(BundleContext context) {
+ s_logger.info("Starting alarmmanager bundle");
+ AlarmNotificationListeners notificationListeners = new AlarmNotificationListeners(context);
+ try {
+ listener = notificationListeners;
+ listenerThread = new Thread(listener);
+ listenerThread.start();
+ } catch (Exception e) {
+ s_logger.error("Exception in alarm thread {}", e);
+ }
+ }
+
+ public void stop(BundleContext context) {
+ s_logger.info("Stopping alarmmanager bundle");
+ }
+}
\ 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.fcapsmanager.alarmmanager;
+
+import javax.management.*;
+import java.lang.management.ManagementFactory;
+import java.util.*;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.opendaylight.vpnservice.fcapsmanager.AlarmServiceFacade;
+
+public class AlarmNotificationListeners implements Runnable {
+ static Logger s_logger = LoggerFactory.getLogger(AlarmNotificationListeners.class);
+ private MBeanServer mbs = null;
+ private static String DOMAIN = "SDNC.FM";
+
+ private final DelegateListener delegateListener = new DelegateListener();
+ private BundleContext context = null;
+
+ public AlarmNotificationListeners(BundleContext context) {
+ this.context=context;
+ }
+
+ /**
+ * Platform dependent bundle injects its handle and it is retrieved in the method
+ */
+ private AlarmServiceFacade getAlarmServiceSPI (){
+ AlarmServiceFacade service =null;
+ if(context != null) {
+ try {
+ ServiceReference<?> serviceReference = context.
+ getServiceReference(AlarmServiceFacade.class.getName());
+ service = (AlarmServiceFacade) context.
+ getService(serviceReference);
+ }catch (NullPointerException ex){
+ service = null;
+ }catch (Exception e){
+ s_logger.error("Exception {} occurred in getting AlarmServiceSPI",e);
+ }
+ }
+ return service;
+ }
+
+ /**
+ * Gets register notification when a mbean is registered in platform Mbeanserver and checks if it is alarm mbean and add attribute notification listener to it.
+ * Gets attribute notification when alarm mbean is updated by the application.
+ */
+ public class DelegateListener implements NotificationListener {
+ public void handleNotification(Notification notification, Object obj) {
+ if (notification instanceof MBeanServerNotification) {
+ MBeanServerNotification msnotification =
+ (MBeanServerNotification) notification;
+ String nType = msnotification.getType();
+ ObjectName mbn = msnotification.getMBeanName();
+
+ if (nType.equals("JMX.mbean.registered")) {
+ if (mbn.toString().contains(DOMAIN)) {
+ s_logger.debug("Received registeration of Mbean "+mbn);
+ try {
+ mbs.addNotificationListener(mbn,delegateListener, null, null);
+ s_logger.debug("Added attribute notification listener for Mbean "+ mbn);
+ } catch (InstanceNotFoundException e) {
+ s_logger.error("Exception while adding attribute notification of mbean {}", e);
+ }
+ }
+ }
+
+ if (nType.equals("JMX.mbean.unregistered")) {
+ if (mbn.toString().contains(DOMAIN)) {
+ s_logger.debug("Time: " + msnotification.getTimeStamp() + "MBean " + msnotification.getMBeanName()+" unregistered successfully");
+ }
+ }
+ }
+ else if (notification instanceof AttributeChangeNotification) {
+ AttributeChangeNotification acn =
+ (AttributeChangeNotification) notification;
+
+ s_logger.debug("Received attribute notification of Mbean: "
+ + notification.getSource()
+ + " for attribute:" + acn.getAttributeName() );
+
+ if(acn.getAttributeName().toString().equals("raiseAlarmObject")){
+
+ String value=acn.getNewValue().toString();
+ value = value.replace(value.charAt(0), ' ');
+ value = value.replace(value.charAt(value.lastIndexOf("]")), ' ');
+
+ String[] args =value.split(",");
+ s_logger.debug("Receive attribute value :"+args[0].trim()+args[1].trim()+args[2].trim());
+ if(getAlarmServiceSPI() != null ) {
+ getAlarmServiceSPI().raiseAlarm(args[0].trim(),args[1].trim(),args[2].trim());
+ } else {
+ s_logger.debug("Alarm service not available");
+ }
+
+ } else if(acn.getAttributeName().toString().equals("clearAlarmObject")){
+
+ String value=acn.getNewValue().toString();
+ value = value.replace(value.charAt(0), ' ');
+ value = value.replace(value.charAt(value.lastIndexOf("]")), ' ');
+
+ String[] args =value.split(",");
+ s_logger.debug("Receive attribute value :"+args[0].trim()+args[1].trim()+args[2].trim());
+ if(getAlarmServiceSPI() != null )
+ getAlarmServiceSPI().clearAlarm(args[0].trim(), args[1].trim(), args[2].trim());
+ else
+ s_logger.debug("Alarm service not available");
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the platform MBeanServer instance and registers to get notification whenever alarm mbean is registered in the mbeanserver
+ */
+ @Override
+ public void run() {
+ mbs = ManagementFactory.getPlatformMBeanServer();
+
+ queryMbeans();
+
+ ObjectName delegate = null;
+ try {
+ delegate = new ObjectName("JMImplementation:type=MBeanServerDelegate");
+ } catch (MalformedObjectNameException e) {
+ e.printStackTrace();
+ }
+ NotificationFilterSupport filter = new NotificationFilterSupport();
+ filter.enableType("JMX.mbean.registered");
+ filter.enableType("JMX.mbean.unregistered");
+
+ try {
+ mbs.addNotificationListener(delegate, delegateListener, filter, null);
+ s_logger.debug("Added registeration listener for Mbean {}",delegate);
+ } catch (InstanceNotFoundException e) {
+ s_logger.error("Failed to add registeration listener {}", e);
+ }
+
+ waitForNotification();
+ }
+
+ /**
+ * Pre-provisioning case to handle all alarm mbeans which are registered before installation of framework bundle
+ * Queries the platform Mbeanserver to retrieve registered alarm mbean and add attribute notification listener to it
+ */
+ public void queryMbeans() {
+
+ Set<ObjectName> names =
+ new TreeSet<ObjectName>(mbs.queryNames(null, null));
+ s_logger.debug("Queried MBeanServer for MBeans:");
+ for (ObjectName beanName : names) {
+ if(beanName.toString().contains(DOMAIN)){
+ try {
+ mbs.addNotificationListener(beanName,delegateListener, null, null);
+ s_logger.debug("Added attribute notification listener for Mbean "+ beanName);
+ } catch (InstanceNotFoundException e) {
+ s_logger.error("Failed to add attribute notification for Mbean {}", e);
+ }
+ }
+ }
+ }
+ public void waitForNotification() {
+ while(true){
+ try {
+ Thread.sleep(50);
+ }
+ catch(Exception ex){
+ ex.printStackTrace();
+ }
+ }
+ }
+}
\ 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) 2015 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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>countermanager</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <maven-bundle-plugin.version>2.5.3</maven-bundle-plugin.version>
+ <osgi.version>5.0.0</osgi.version>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>${osgi.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>fcaps-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven-bundle-plugin.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+ <Bundle-Version>${project.version}</Bundle-Version>
+ <Bundle-Activator>org.opendaylight.vpnservice.fcapsmanager.countermanager.Activator</Bundle-Activator>
+ <Export-Package>org.opendaylight.vpnservice.fcapsmanager.countermanager*;version=${project.version}</Export-Package>
+ <Import-Package>*</Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
\ 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.fcapsmanager.countermanager;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MalformedObjectNameException;
+import javax.management.ReflectionException;
+import java.io.IOException;
+
+public class Activator implements BundleActivator {
+ private final static org.slf4j.Logger LOG = LoggerFactory.getLogger(Activator.class);
+ private Runnable listener;
+ private Thread listenerThread;
+
+ public void start(BundleContext context) throws InstanceNotFoundException, MalformedObjectNameException, MBeanException, ReflectionException, IOException {
+ LOG.info("Starting countermanager bundle ");
+ PMRegistrationListener notificationListeners = new PMRegistrationListener(context);
+ try {
+ listener = notificationListeners;
+ listenerThread = new Thread(listener);
+ listenerThread.start();
+ } catch (Exception e) {
+ LOG.error("Exception in counter thread {}", e);
+ }
+ }
+
+ public void stop(BundleContext context) {
+ LOG.info("Stopping countermanager bundle ");
+ }
+}
\ 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.fcapsmanager.countermanager;
+
+import java.lang.management.ManagementFactory;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerNotification;
+import javax.management.MalformedObjectNameException;
+import javax.management.Notification;
+import javax.management.NotificationFilterSupport;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+
+import org.osgi.framework.BundleContext;
+import org.slf4j.LoggerFactory;
+
+public class PMRegistrationListener implements Runnable {
+ private final static org.slf4j.Logger LOG = LoggerFactory.getLogger(PMRegistrationListener.class);
+ static MBeanServer mbs = null;
+
+ private static String DOMAIN = "SDNC.PM";
+ public static HashSet<ObjectName> beanNames = new HashSet<ObjectName>();
+ private BundleContext context = null;
+
+ public PMRegistrationListener(BundleContext context){
+ this.context=context;
+ }
+
+ /**
+ * Gets register notification when a mbean is registered in platform Mbeanserver and checks if it is counter mbean and add it to the map.
+ */
+ public static class DelegateListener implements NotificationListener {
+ public void handleNotification(Notification notification, Object obj) {
+ if (notification instanceof MBeanServerNotification) {
+ MBeanServerNotification msnotification =
+ (MBeanServerNotification) notification;
+ String nType = msnotification.getType();
+ ObjectName mbn = msnotification.getMBeanName();
+ if (nType.equals("JMX.mbean.registered")) {
+ String mbean = mbn.toString();
+ if(mbean.contains(DOMAIN)) {
+ beanNames.add(mbn);
+ LOG.debug("Beans are " +beanNames);
+ }
+ }
+ if (nType.equals("JMX.mbean.unregistered")) {
+ if(mbn.toString().contains(DOMAIN)) {
+ beanNames.remove(mbn);
+ LOG.debug(mbn +" MBean has been unregistered");
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void run(){
+ mbs = ManagementFactory.getPlatformMBeanServer();
+ queryMbeans();
+ DelegateListener delegateListener = new DelegateListener();
+ ObjectName delegate = null;
+ try {
+ delegate = new ObjectName("JMImplementation:type=MBeanServerDelegate");
+ } catch (MalformedObjectNameException e) {
+ e.printStackTrace();
+ }
+ NotificationFilterSupport filter = new NotificationFilterSupport();
+
+ filter.enableType("JMX.mbean.registered");
+ filter.enableType("JMX.mbean.unregistered");
+
+ LOG.debug("Add PM Registeration Notification Listener");
+ try {
+ mbs.addNotificationListener(delegate, delegateListener, filter,null);
+ }catch (InstanceNotFoundException e) {
+ e.printStackTrace();
+ }
+ Poller poller = new Poller(this.context);
+ poller.polling();
+ waitforNotification();
+ }
+
+ /**
+ * Prepovising case to handle all counter mbeans which are registered before the installation of framework bundle
+ * Queries the platform Mbeanserver to retrieve registered counter mbean and add it to the map
+ */
+ public void queryMbeans() {
+ Set<ObjectName> names =
+ new TreeSet<ObjectName>(mbs.queryNames(null, null));
+ LOG.debug("\nQueried MBeanServer for MBeans:");
+ for (ObjectName name : names) {
+ if(name.toString().contains(DOMAIN)){
+ beanNames.add(name);
+ }
+ }
+ }
+
+ private void waitforNotification() {
+ while(true){
+ try {
+ Thread.sleep(50);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
\ 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.fcapsmanager.countermanager;
+
+import java.lang.management.ManagementFactory;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.LoggerFactory;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import org.opendaylight.vpnservice.fcapsmanager.PMServiceFacade;
+
+public class Poller {
+ private final static org.slf4j.Logger LOG = LoggerFactory.getLogger(Poller.class);
+ private static BundleContext context = null;
+ public Poller(){
+ }
+ public Poller(BundleContext bundleContext) {
+ context = bundleContext;
+ }
+ //This method do the Polling every 5 second and retrieves the the counter details
+ //@Override
+ public void polling() {
+ LOG.debug("Poller Polling Mbean List and the content is " + PMRegistrationListener.beanNames);
+ ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
+ service.scheduleAtFixedRate(new Pollerthread(), 0, 5, TimeUnit.SECONDS);
+ }
+
+ /**
+ * Platform dependent bundle injects its handle and it is retrieved in the method
+ */
+ protected PMServiceFacade getPMServiceSPI (){
+ PMServiceFacade service =null;
+ if(context != null) {
+ try {
+ ServiceReference<?> serviceReference = context.
+ getServiceReference(PMServiceFacade.class.getName());
+ service = (PMServiceFacade) context.
+ getService(serviceReference);
+ }catch(NullPointerException ex){
+ service = null;
+ }catch (Exception e){
+ LOG.error("Exception {} occurred in getting PMServiceSPI",e);
+ }
+ }
+ return service;
+ }
+}
+
+class Pollerthread implements Runnable {
+ private final static org.slf4j.Logger LOG = LoggerFactory.getLogger(Pollerthread.class);
+ MBeanServer mbs = null;
+ Map<String,String> getCounter = new HashMap<String,String>();
+ Poller poller = new Poller();
+
+ /**
+ * Retrieve countermap from each counter mbean and send to platform
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public void run() {
+ try {
+ mbs = ManagementFactory.getPlatformMBeanServer();
+ for (ObjectName objectName : PMRegistrationListener.beanNames) {
+ getCounter=(Map<String, String>) mbs.invoke(objectName, "retrieveCounterMap",null,null);
+ if(poller.getPMServiceSPI() != null)
+ poller.getPMServiceSPI().connectToPMFactory(getCounter);
+ else
+ LOG.debug("PM service not available");
+ }
+ } catch (Exception e) {
+ LOG.error("Exception caught {} ", e);
+ }
+ }
+}
\ 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) 2015 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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>fcaps-api</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <maven-bundle-plugin.version>2.5.3</maven-bundle-plugin.version>
+ <osgi.version>5.0.0</osgi.version>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>${osgi.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>${maven-bundle-plugin.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+ <Bundle-Version>${project.version}</Bundle-Version>
+ <Bundle-Activator>org.opendaylight.vpnservice.fcapsmanager.Activator</Bundle-Activator>
+ <Export-Package>org.opendaylight.vpnservice.fcapsmanager*;version=${project.version}</Export-Package>
+ <Import-Package>*</Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
\ 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.fcapsmanager;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class Activator implements BundleActivator {
+ static Logger s_logger = LoggerFactory.getLogger(Activator.class);
+ public void start(BundleContext context) {
+ s_logger.info("Starting fcapsSPI bundle");
+ }
+
+ public void stop(BundleContext context) {
+ s_logger.info("Stopping fcapsSPI bundle");
+ }
+
+}
\ 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.fcapsmanager;
+
+public interface AlarmServiceFacade {
+ /**
+ * Raises the given alarm in platform environment
+ *
+ * @param alarmName
+ * Alarm to be raised
+ * @param additionalText
+ * Additional details describing about the alarm
+ * @param source
+ * Source of the alarm ex: dpnId=openflow:1
+ * the source node that caused this alarm
+ */
+ public void raiseAlarm(String alarmName, String additionalText, String source);
+
+ /**
+ * Clears the given alarm in platform environment
+ *
+ * @param alarmName
+ * Alarm to be cleared
+ * @param additionalText
+ * Additional details describing about the alarm
+ * @param source
+ * Source of the alarm ex: dpnId=openflow:1
+ * the source node that caused this alarm
+ */
+ public void clearAlarm(String alarmName, String additionalText, String source);
+}
\ 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.fcapsmanager;
+
+import java.util.Map;
+
+public interface PMServiceFacade {
+ public void connectToPMFactory(Map map);
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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,
+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.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>fcapsmanager</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <name>fcapsmanager</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>fcaps-api</module>
+ <module>alarmmanager</module>
+ <module>countermanager</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>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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,
+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>features-parent</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>vpnservice-features</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <name>${project.artifactId}</name>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <properties>
+ <mdsal.version>1.4.0-SNAPSHOT</mdsal.version>
+ <openflowplugin.version>0.3.0-SNAPSHOT</openflowplugin.version>
+ <restconf.version>1.4.0-SNAPSHOT</restconf.version>
+ <yangtools.version>1.0.0-SNAPSHOT</yangtools.version>
+ <mdsal.model.version>0.9.0-SNAPSHOT</mdsal.model.version>
+ <vpnservices.version>0.3.0-SNAPSHOT</vpnservices.version>
+ <ovsdb.version>1.3.0-SNAPSHOT</ovsdb.version>
+ <liblldp.version>0.11.0-SNAPSHOT</liblldp.version>
+ <neutron.version>0.7.0-SNAPSHOT</neutron.version>
+ <nic.version>1.2.0-SNAPSHOT</nic.version>
+ <arputil.version>${vpnservices.version}</arputil.version>
+ <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>
+ <idmanager.version>${vpnservices.version}</idmanager.version>
+ <itm.version>${vpnservices.version}</itm.version>
+ <neutronvpn.version>${vpnservices.version}</neutronvpn.version>
+ <fcaps.manager.version>${vpnservices.version}</fcaps.manager.version>
+ <fcaps.app.version>${vpnservices.version}</fcaps.app.version>
+ </properties>
+ <dependencyManagement>
+ <dependencies>
+ <!-- project specific dependencies -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>mdsal-artifacts</artifactId>
+ <version>${mdsal.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>restconf-artifacts</artifactId>
+ <version>${restconf.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>features-yangtools</artifactId>
+ <classifier>features</classifier>
+ <version>${yangtools.version}</version>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>features-mdsal</artifactId>
+ <classifier>features</classifier>
+ <version>${mdsal.version}</version>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>features-mdsal-model</artifactId>
+ <version>${mdsal.model.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.nic</groupId>
+ <artifactId>features-nic</artifactId>
+ <classifier>features</classifier>
+ <version>${nic.version}</version>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.ovsdb</groupId>
+ <artifactId>southbound-features</artifactId>
+ <version>${ovsdb.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.ovsdb</groupId>
+ <artifactId>hwvtepsouthbound-features</artifactId>
+ <version>${ovsdb.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>features-openflowplugin</artifactId>
+ <classifier>features</classifier>
+ <version>${openflowplugin.version}</version>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>features-restconf</artifactId>
+ <classifier>features</classifier>
+ <version>${restconf.version}</version>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.neutron</groupId>
+ <artifactId>features-neutron</artifactId>
+ <classifier>features</classifier>
+ <version>${neutron.version}</version>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.neutron</groupId>
+ <artifactId>dummyprovider</artifactId>
+ <version>${neutron.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>vpnmanager-impl</artifactId>
+ <version>${vpnmanager.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>vpnmanager-impl</artifactId>
+ <version>${vpnmanager.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mdsalutil-impl</artifactId>
+ <version>${mdsalutil.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>arputil-api</artifactId>
+ <version>${arputil.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>arputil-impl</artifactId>
+ <version>${arputil.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>arputil-impl</artifactId>
+ <version>${arputil.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mdsalutil-impl</artifactId>
+ <version>${mdsalutil.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mdsalutil-api</artifactId>
+ <version>${mdsalutil.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>interfacemgr-impl</artifactId>
+ <version>${interfacemgr.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>interfacemgr-impl</artifactId>
+ <version>${interfacemgr.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>interfacemgr-api</artifactId>
+ <version>${interfacemgr.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>interfacemgr-shell</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>
+ <version>${liblldp.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>alivenessmonitor-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>alivenessmonitor-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>alivenessmonitor-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>vpnmanager-api</artifactId>
+ <version>${vpnmanager.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgpmanager-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgpmanager-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgpmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>model-bgp</artifactId>
+ <version>2013.07.15.9-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>fibmanager-impl</artifactId>
+ <version>${fibmanager.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>fibmanager-impl</artifactId>
+ <version>${fibmanager.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>fibmanager-shell</artifactId>
+ <version>${fibmanager.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>fibmanager-api</artifactId>
+ <version>${fibmanager.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>lockmanager-impl</artifactId>
+ <version>${lockmanager.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>lockmanager-impl</artifactId>
+ <version>${lockmanager.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>lockmanager-api</artifactId>
+ <version>${lockmanager.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>idmanager-impl</artifactId>
+ <version>${idmanager.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>idmanager-impl</artifactId>
+ <version>${idmanager.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>idmanager-api</artifactId>
+ <version>${idmanager.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>itm-impl</artifactId>
+ <version>${itm.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>itm-impl</artifactId>
+ <version>${itm.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>itm-api</artifactId>
+ <version>${itm.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>dhcpservice-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>dhcpservice-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>dhcpservice-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>natservice-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>natservice-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>natservice-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>neutronvpn-api</artifactId>
+ <version>${neutronvpn.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>neutronvpn-impl</artifactId>
+ <version>${neutronvpn.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>neutronvpn-impl</artifactId>
+ <version>${neutronvpn.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>neutronvpn-shell</artifactId>
+ <version>${neutronvpn.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.thrift</groupId>
+ <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>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>vpnintent-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>vpnintent-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>vpnintent-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>alarmmanager</artifactId>
+ <version>${fcaps.manager.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>countermanager</artifactId>
+ <version>${fcaps.manager.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>fcaps-api</artifactId>
+ <version>${fcaps.manager.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>fcapsapplication-jmxapi</artifactId>
+ <version>${fcaps.app.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>fcapsapplication-impl</artifactId>
+ <version>${fcaps.app.version}</version>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+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,
+and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<features name="odl-vpnservice-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+ <repository>mvn:org.opendaylight.yangtools/features-yangtools/{{VERSION}}/xml/features</repository>
+ <repository>mvn:org.opendaylight.controller/features-mdsal/{{VERSION}}/xml/features</repository>
+ <repository>mvn:org.opendaylight.mdsal.model/features-mdsal-model/{{VERSION}}/xml/features</repository>
+ <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin/{{VERSION}}/xml/features</repository>
+ <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin-extension/{{VERSION}}/xml/features</repository>
+ <repository>mvn:org.opendaylight.netconf/features-restconf/{{VERSION}}/xml/features</repository>
+ <repository>mvn:org.opendaylight.ovsdb/southbound-features/{{VERSION}}/xml/features</repository>
+ <repository>mvn:org.opendaylight.neutron/features-neutron/{{VERSION}}/xml/features</repository>
+ <repository>mvn:org.opendaylight.nic/features-nic/{{VERSION}}/xml/features</repository>
+ <repository>mvn:org.opendaylight.ovsdb/hwvtepsouthbound-features/{{VERSION}}/xml/features</repository>
+ <feature name='odl-vpnservice-api' version='${project.version}' description='OpenDaylight :: vpnservice :: api '>
+ <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>
+ <feature version='${ovsdb.version}'>odl-ovsdb-hwvtepsouthbound-api</feature>
+ <bundle>mvn:org.opendaylight.controller/liblldp/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.neutron/model/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/model-bgp/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/lockmanager-api/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/idmanager-api/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/mdsalutil-api/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/arputil-api/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/alivenessmonitor-api/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/interfacemgr-api/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/vpnmanager-api/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/fibmanager-api/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/itm-api/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/neutronvpn-api/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/dhcpservice-api/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/natservice-api/{{VERSION}}</bundle>
+ </feature>
+ <feature name='odl-vpnservice-impl' version='${project.version}' description='OpenDaylight :: vpnservice :: impl '>
+ <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
+ <feature version="${ovsdb.version}">odl-ovsdb-southbound-impl-rest</feature>
+ <feature version='${ovsdb.version}'>odl-ovsdb-hwvtepsouthbound</feature>
+ <feature version='${project.version}'>odl-vpnservice-api</feature>
+ <feature version="${openflowplugin.version}">odl-openflowplugin-southbound</feature>
+ <feature version="${openflowplugin.version}">odl-openflowplugin-flow-services</feature>
+ <bundle>mvn:commons-net/commons-net/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/lockmanager-impl/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/idmanager-impl/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/bgpmanager-api/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/bgpmanager-impl/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/mdsalutil-api/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/arputil-impl/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/alivenessmonitor-impl/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/mdsalutil-impl/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/interfacemgr-api/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/interfacemgr-impl/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/interfacemgr-shell/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/vpnmanager-impl/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/fibmanager-impl/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/fibmanager-shell/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/itm-impl/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/neutronvpn-impl/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/neutronvpn-shell/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/dhcpservice-impl/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/elanmanager-api/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/elanmanager-impl/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/natservice-impl/{{VERSION}}</bundle>
+
+ <!--<bundle>mvn:org.opendaylight.vpnservice.third-party/org.apache.thriftlib/1.1.0-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>
+ <!--<bundle>wrap:mvn:javax.servlet/servlet-api/2.5</bundle>-->
+ <configfile finalname="lockmanager-impl-default-config.xml">mvn:org.opendaylight.vpnservice/lockmanager-impl/{{VERSION}}/xml/config</configfile>
+ <configfile finalname="idmanager-impl-default-config.xml">mvn:org.opendaylight.vpnservice/idmanager-impl/{{VERSION}}/xml/config</configfile>
+ <configfile finalname="idmanager-impl-default-config.xml">mvn:org.opendaylight.vpnservice/idmanager-impl/{{VERSION}}/xml/config</configfile>
+ <configfile finalname="bgpmanager-impl-default-config.xml">mvn:org.opendaylight.vpnservice/bgpmanager-impl/{{VERSION}}/xml/config</configfile>
+ <configfile finalname="mdsalutil-impl-default-config.xml">mvn:org.opendaylight.vpnservice/mdsalutil-impl/{{VERSION}}/xml/config</configfile>
+ <configfile finalname="interfacemgr-impl-default-config.xml">mvn:org.opendaylight.vpnservice/interfacemgr-impl/{{VERSION}}/xml/config</configfile>
+ <configfile finalname="arputil-impl-default-config.xml">mvn:org.opendaylight.vpnservice/arputil-impl/{{VERSION}}/xml/config</configfile>
+ <configfile finalname="alivenessmonitor-impl-default-config.xml">mvn:org.opendaylight.vpnservice/alivenessmonitor-impl/{{VERSION}}/xml/config</configfile>
+ <configfile finalname="vpnmanager-impl-default-config.xml">mvn:org.opendaylight.vpnservice/vpnmanager-impl/{{VERSION}}/xml/config</configfile>
+ <configfile finalname="fibmanager-impl-default-config.xml">mvn:org.opendaylight.vpnservice/fibmanager-impl/{{VERSION}}/xml/config</configfile>
+ <configfile finalname="itm-impl-default-config.xml">mvn:org.opendaylight.vpnservice/itm-impl/{{VERSION}}/xml/config</configfile>
+ <configfile finalname="neutronvpn-impl-default-config.xml">mvn:org.opendaylight.vpnservice/neutronvpn-impl/{{VERSION}}/xml/config</configfile>
+ <configfile finalname="dhcpservice-impl-default-config.xml">mvn:org.opendaylight.vpnservice/dhcpservice-impl/{{VERSION}}/xml/config</configfile>
+ <configfile finalname="elanmanager-impl-default-config.xml">mvn:org.opendaylight.vpnservice/elanmanager-impl/{{VERSION}}/xml/config</configfile>
+ <configfile finalname="natservice-impl-default-config.xml">mvn:org.opendaylight.vpnservice/natservice-impl/{{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>
+ <feature version="${restconf.version}">odl-restconf</feature>
+ </feature>
+ <feature name='odl-vpnservice-impl-ui' version='${project.version}' description='OpenDaylight :: vpnservice :: impl :: UI'>
+ <feature version="${project.version}">odl-vpnservice-impl-rest</feature>
+ <feature version="${restconf.version}">odl-mdsal-apidocs</feature>
+ <feature version="${mdsal.version}">odl-mdsal-xsql</feature>
+ </feature>
+ <feature name='odl-vpnservice-core' version='${project.version}' description='OpenDaylight :: vpnservice :: core'>
+ <feature version="${neutron.version}">odl-neutron-service</feature>
+ <bundle>mvn:org.opendaylight.neutron/dummyprovider/{{VERSION}}</bundle>
+ <feature version="${project.version}">odl-vpnservice-impl-ui</feature>
+ </feature>
+ <feature name='odl-vpnservice-openstack' version='${project.version}' description='OpenDaylight :: vpnservice :: openstack'>
+ <feature version="${neutron.version}">odl-neutron-service</feature>
+ <bundle>mvn:org.opendaylight.neutron/dummyprovider/{{VERSION}}</bundle>
+ <feature version="${project.version}">odl-vpnservice-impl-rest</feature>
+ </feature>
+ <feature name='odl-vpnservice-intent' version='${project.version}' description='OpenDaylight :: vpnservice :: intent'>
+ <feature version='${mdsal.version}'>odl-mdsal-broker</feature>
+ <feature version='${nic.version}'>odl-nic-listeners</feature>
+ <bundle>mvn:org.opendaylight.vpnservice/vpnintent-api/{{VERSION}}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/vpnintent-impl/{{VERSION}}</bundle>
+ <configfile finalname="vpnintent-impl-default-config.xml">mvn:org.opendaylight.vpnservice/vpnintent-impl/{{VERSION}}/xml/config</configfile>
+ </feature>
+ <feature name='odl-fcaps-framework' version='${project.version}' description='OpenDaylight :: fcapsframework'>
+ <bundle>mvn:org.opendaylight.vpnservice/fcaps-api/${fcaps.manager.version}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/alarmmanager/${fcaps.manager.version}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/countermanager/${fcaps.manager.version}</bundle>
+ </feature>
+ <feature name='odl-fcaps-application' version='${project.version}' description='OpenDaylight :: fcapsapp'>
+ <feature version="${openflowplugin.version}">odl-openflowplugin-all</feature>
+ <bundle>mvn:org.opendaylight.vpnservice/fcapsapplication-jmxapi/${fcaps.app.version}</bundle>
+ <bundle>mvn:org.opendaylight.vpnservice/fcapsapplication-impl/${fcaps.app.version}</bundle>
+ <configfile finalname="etc/opendaylight/karaf/73-fcaps-app.xml">mvn:org.opendaylight.vpnservice/fcapsapplication-impl/${fcaps.app.version}/xml/config </configfile>
+ </feature>
+ </features>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>fibmanager-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.yangtools</groupId>
+ <artifactId>yang-common</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>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.model</groupId>
+ <artifactId>model-flow-base</artifactId>
+ <version>${openflowplugin.version}</version>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.fibmanager.api;
+
+import java.math.BigInteger;
+import java.util.List;
+
+public interface IFibManager {
+ void populateFibOnNewDpn(BigInteger dpnId, long vpnId, String rd);
+ void cleanUpDpnForVpn(BigInteger dpnId, long vpnId, String rd);
+ List<String> printFibEntries();
+ void addStaticRoute(String prefix, String nextHop, String rd, int label);
+ void deleteStaticRoute(String prefix, String rd);
+}
--- /dev/null
+module fib-rpc {\r
+ namespace "urn:opendaylight:vpnservice:fib:rpc";\r
+ prefix "fib-rpc";\r
+\r
+ import ietf-inet-types {\r
+ prefix inet;\r
+ revision-date "2010-09-24";\r
+ }\r
+\r
+ import opendaylight-flow-types {\r
+ prefix offlow;\r
+ revision-date "2013-10-26";\r
+ }\r
+\r
+ revision "2016-01-21" {\r
+ description "FIB Servicer RPC Module";\r
+ }\r
+\r
+ /* RPCs */\r
+\r
+ rpc create-fib-entry {\r
+ description "to install FIB/LFIB/TST routes on specified dpn with given instructions";\r
+ input {\r
+ leaf source-dpid {\r
+ type uint64;\r
+ }\r
+ leaf vpn-name {\r
+ type string;\r
+ }\r
+ leaf service-id {\r
+ type uint32;\r
+ }\r
+ leaf ip-address {\r
+ type string;\r
+ }\r
+ uses offlow:instruction-list;\r
+ }\r
+ }\r
+\r
+ rpc remove-fib-entry {\r
+ description "to remove FIB/LFIB/TST routes from specified dpn";\r
+ input {\r
+ leaf source-dpid {\r
+ type uint64;\r
+ }\r
+ leaf vpn-name {\r
+ type string;\r
+ }\r
+ leaf service-id {\r
+ type uint32;\r
+ }\r
+ leaf ip-address {\r
+ type string;\r
+ }\r
+ }\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+module fibmanager-api {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:fibmanager:api";
+ prefix "fibmanager-api";
+
+ import config { prefix config; revision-date 2013-04-05; }
+
+ description
+ "Service definition for vpnmanager project";
+
+ revision "2015-05-08" {
+ description
+ "Initial revision";
+ }
+
+ identity fibmanager-api {
+ base "config:service-type";
+ config:java-class "org.opendaylight.fibmanager.api.IFibManager";
+ }
+}
\ No newline at end of file
--- /dev/null
+module l3nexthop {
+ namespace "urn:opendaylight:vpnservice:l3nexthop";
+ prefix l3nexthop;
+
+ revision "2015-04-09" {
+ description "L3 NextHop module";
+ }
+
+ container l3nexthop {
+ config false;
+ list vpnNexthops{
+ key "vpnId";
+ leaf vpnId {type uint32;}
+ list vpnNexthop{
+ key "IpAddress";
+ leaf IpAddress {type string;}
+ leaf egressPointer {type uint32;}
+ leaf dpnId {type uint64;}
+ leaf flowrefCount {type uint16; }
+ }
+ }
+ list tunnelNexthops{
+ key "dpnId";
+ leaf dpnId {type uint64;}
+ list tunnelNexthop{
+ key "IpAddress";
+ leaf IpAddress {type string;}
+ leaf egressPointer {type uint32;}
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+module odl-fib {
+ namespace "urn:opendaylight:vpnservice:fibmanager";
+ prefix odl-fib;
+
+ revision "2015-03-30" {
+ description "FIB Manager module";
+ }
+
+ grouping ipv4Entries{
+ list ipv4Entry{
+ key "destPrefix";
+ leaf destPrefix {type string;}
+ leaf nextHopAddress {type string;}
+ }
+ }
+
+ grouping vrfEntries{
+ list vrfEntry{
+ key "destPrefix";
+ leaf destPrefix {
+ type string;
+ mandatory true;
+ }
+ leaf label {
+ type uint32;
+ mandatory true;
+ }
+ leaf nextHopAddress {
+ type string;
+ }
+ }
+ }
+
+ container fibEntries {
+ config true;
+ list vrfTables{
+ key "routeDistinguisher";
+ leaf routeDistinguisher {type string;}
+ uses vrfEntries;
+ }
+
+ container ipv4Table{
+ uses ipv4Entries;
+ }
+ }
+}
\ 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) 2015 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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>fibmanager-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>fibmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mdsalutil-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>itm-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>vpnmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>idmanager-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.openflowplugin.model</groupId>
+ <artifactId>model-flow-service</artifactId>
+ <version>${openflowplugin.version}</version>
+ </dependency>
+ </dependencies>
+
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+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,
+and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<snapshot>
+ <required-capabilities>
+ <capability>urn:opendaylight:params:xml:ns:yang:fibmanager:impl?module=fibmanager-impl&revision=2015-03-25</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:vpnmanager:api?module=vpnmanager-api&revision=2015-05-08</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:mdsalutil:api?module=odl-mdsalutil&revision=2015-04-10</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</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:fibmanager:impl">prefix:fibmanager-impl</type>
+ <name>fibmanager-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>
+ <vpnmanager>
+ <type xmlns:odl-vpn="urn:opendaylight:params:xml:ns:yang:vpnmanager:api">odl-vpn:vpnmanager-api</type>
+ <name>vpnmanager</name>
+ </vpnmanager>
+ </module>
+ </modules>
+ <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <service>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:fibmanager:api">prefix:fibmanager-api</type>
+ <instance>
+ <name>fibmanager</name>
+ <provider>/modules/module[type='fibmanager-impl'][name='fibmanager-default']</provider>
+ </instance>
+ </service>
+ </services>
+ </data>
+ </configuration>
+</snapshot>
--- /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.fibmanager;
+
+import java.math.BigInteger;
+
+public class FibConstants {
+ static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000002", 16);
+ static final BigInteger COOKIE_VM_FIB_TABLE = new BigInteger("8000003", 16);
+ static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
+ static final int DEFAULT_FIB_FLOW_PRIORITY = 10;
+ static final String FLOWID_PREFIX = "L3.";
+ static final String VPN_IDPOOL_NAME = "vpnservices";
+ static final String SEPARATOR = ".";
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.fibmanager;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+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.binding.api.DataChangeListener;
+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.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnmanager.api.IVpnManager;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.vpnservice.itm.globals.ITMConstants;
+import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.ActionType;
+import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
+import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
+import org.opendaylight.vpnservice.mdsalutil.InstructionType;
+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.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.PrefixToInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.RdToElanOp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.rd.to.elan.op.RdToElanOpEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.rd.to.elan.op.RdToElanOpEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnToExtraroute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.VpnIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.VpnIdsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.Vpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.VpnKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.Extraroute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.FibEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeMplsOverGre;
+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.GetTunnelTypeInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetTunnelTypeOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FibManager extends AbstractDataChangeListener<VrfEntry> implements AutoCloseable{
+ private static final Logger LOG = LoggerFactory.getLogger(FibManager.class);
+ private static final String FLOWID_PREFIX = "L3.";
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private IMdsalApiManager mdsalManager;
+ private IVpnManager vpnmanager;
+ private NexthopManager nextHopManager;
+ private ItmRpcService itmManager;
+ private OdlInterfaceRpcService interfaceManager;
+ private IdManagerService idManager;
+ private static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000002", 16);
+ private static final BigInteger COOKIE_VM_FIB_TABLE = new BigInteger("8000003", 16);
+ private static final int DEFAULT_FIB_FLOW_PRIORITY = 10;
+ private static final BigInteger METADATA_MASK_CLEAR = new BigInteger("000000FFFFFFFFFF", 16);
+ private static final BigInteger CLEAR_METADATA = BigInteger.valueOf(0);
+ public static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
+
+
+ public FibManager(final DataBroker db) {
+ super(VrfEntry.class);
+ broker = db;
+ registerListener(db);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("Fib Manager Closed");
+ }
+
+ public void setNextHopManager(NexthopManager nextHopManager) {
+ this.nextHopManager = nextHopManager;
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ public void setVpnmanager(IVpnManager vpnmanager) {
+ this.vpnmanager = vpnmanager;
+ }
+
+ public void setITMRpcService(ItmRpcService itmManager) {
+ this.itmManager = itmManager;
+ }
+
+ public void setInterfaceManager(OdlInterfaceRpcService ifManager) {
+ this.interfaceManager = ifManager;
+ }
+
+ public void setIdManager(IdManagerService idManager) {
+ this.idManager = idManager;
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ getWildCardPath(), FibManager.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("FibManager DataChange listener registration fail!", e);
+ throw new IllegalStateException("FibManager registration Listener failed.", e);
+ }
+ }
+
+
+ private InstanceIdentifier<VrfEntry> getWildCardPath() {
+ return InstanceIdentifier.create(FibEntries.class).child(VrfTables.class).child(VrfEntry.class);
+ }
+
+
+ @Override
+ protected void add(final InstanceIdentifier<VrfEntry> identifier,
+ final VrfEntry vrfEntry) {
+ LOG.trace("Add key: " + identifier + ", value=" + vrfEntry );
+ createFibEntries(identifier, vrfEntry);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<VrfEntry> identifier, VrfEntry vrfEntry) {
+ LOG.trace("Remove key: " + identifier + ", value=" + vrfEntry);
+ deleteFibEntries(identifier, vrfEntry);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<VrfEntry> identifier, VrfEntry original, VrfEntry update) {
+ LOG.trace("Update key: " + identifier + ", original=" + original + ", update=" + update );
+ createFibEntries(identifier, update);
+ }
+
+ private void createFibEntries(final InstanceIdentifier<VrfEntry> identifier,
+ final VrfEntry vrfEntry) {
+ final VrfTablesKey vrfTableKey = identifier.firstKeyOf(VrfTables.class, VrfTablesKey.class);
+ Preconditions.checkNotNull(vrfTableKey, "VrfTablesKey cannot be null or empty!");
+ Preconditions.checkNotNull(vrfEntry, "VrfEntry cannot be null or empty!");
+
+ VpnInstanceOpDataEntry vpnInstance = getVpnInstance(vrfTableKey.getRouteDistinguisher());
+ Preconditions.checkNotNull(vpnInstance, "Vpn Instance not available " + vrfTableKey.getRouteDistinguisher());
+ Preconditions.checkNotNull(vpnInstance.getVpnId(), "Vpn Instance with rd " + vpnInstance.getVrfId() + " has null vpnId!");
+
+ Collection<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
+ Long vpnId = vpnInstance.getVpnId();
+ String rd = vrfTableKey.getRouteDistinguisher();
+ RdToElanOpEntry rdToElanOpEntry = getRdToElanOpEntry(broker, rd,
+ vrfEntry.getDestPrefix());
+ if (rdToElanOpEntry!=null) {
+ if (vpnToDpnList!=null) {
+ for (VpnToDpnList curDpn : vpnToDpnList) {
+ installSubnetRouteInFib(curDpn.getDpnId(), rdToElanOpEntry, vpnId.longValue(), vrfEntry);
+ }
+ }
+ return;
+ }
+ BigInteger localDpnId = createLocalFibEntry(vpnInstance.getVpnId(),
+ rd, vrfEntry);
+ if (vpnToDpnList != null) {
+ for (VpnToDpnList curDpn : vpnToDpnList) {
+ if (!curDpn.getDpnId().equals(localDpnId)) {
+ createRemoteFibEntry(localDpnId, curDpn.getDpnId(), vpnInstance.getVpnId(),
+ vrfTableKey, vrfEntry);
+ }
+ }
+ }
+ }
+
+ private void installSubnetRouteInFib(BigInteger dpnId, RdToElanOpEntry rdToElanOpEntry,
+ long vpnId, VrfEntry vrfEntry){
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ Long elanTag = rdToElanOpEntry.getElanTag();
+
+ instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { (BigInteger.valueOf(elanTag)).shiftLeft(24), MetaDataUtil.METADATA_MASK_SERVICE }));
+ instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.L3_SUBNET_ROUTE_TABLE }));
+ makeConnectedRoute(dpnId,vpnId,vrfEntry,rdToElanOpEntry.getRd(),
+ instructions,NwConstants.ADD_FLOW);
+
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+ // reinitialize instructions list for LFIB Table
+ instructions = new ArrayList<InstructionInfo>();
+
+ actionsInfos.add(new ActionInfo(ActionType.pop_mpls, new String[]{}));
+ instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+ instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { (BigInteger.valueOf(elanTag)).shiftLeft(24), MetaDataUtil.METADATA_MASK_SERVICE }));
+ instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.L3_SUBNET_ROUTE_TABLE }));
+
+ makeLFibTableEntry(dpnId,vrfEntry.getLabel(),instructions,
+ vrfEntry.getNextHopAddress(),NwConstants.ADD_FLOW);
+ // TODO makeTunnelTableEntry();
+ }
+
+ private RdToElanOpEntry getRdToElanOpEntry(DataBroker broker, String rd, String subnetIp) {
+ InstanceIdentifier<RdToElanOpEntry> id = getRdToElanOpEntryDataPath(rd,subnetIp);
+ Optional<RdToElanOpEntry> sn = read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ if(sn.isPresent()) {
+ return sn.get();
+ }
+ return null;
+ }
+
+ private InstanceIdentifier<RdToElanOpEntry> getRdToElanOpEntryDataPath(String rd, String subnetIp) {
+ return InstanceIdentifier.builder(RdToElanOp.class).child(RdToElanOpEntry.class,
+ new RdToElanOpEntryKey(rd,subnetIp)).build();
+ }
+ private <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;
+ }
+
+ private void makeSubnetRouteTableMissFlow(BigInteger dpnId, int addOrRemove) {
+ final BigInteger COOKIE_TABLE_MISS = new BigInteger("8000004", 16);
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[]{}));
+ instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ String flowRef = getFlowRef(dpnId, NwConstants.L3_SUBNET_ROUTE_TABLE, NwConstants.TABLE_MISS_FLOW);
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, NwConstants.L3_SUBNET_ROUTE_TABLE, flowRef,
+ NwConstants.TABLE_MISS_PRIORITY, "Subnet Route Table Miss", 0, 0, COOKIE_TABLE_MISS, matches, instructions);
+
+ if (addOrRemove == NwConstants.ADD_FLOW) {
+ LOG.debug("Invoking MDSAL to install SubnetRoute Table Miss Entries for DPN" + dpnId);
+ mdsalManager.installFlow(flowEntity);
+ } else {
+ LOG.debug("Invoking MDSAL to remove SubnetRoute Table Miss Entries for DPN " + dpnId);
+ mdsalManager.removeFlow(flowEntity);
+ }
+ }
+
+ private Collection<BigInteger> getDpnsForVpn(VpnInstanceOpDataEntry vpnInstance) {
+ Collection<BigInteger> dpns = new HashSet<>();
+ for(VpnToDpnList dpn : vpnInstance.getVpnToDpnList()) {
+ dpns.add(dpn.getDpnId());
+ }
+
+ return dpns;
+ }
+
+ public BigInteger createLocalFibEntry(Long vpnId, String rd, VrfEntry vrfEntry) {
+ BigInteger localDpnId = BigInteger.ZERO;
+ Prefixes localNextHopInfo = getPrefixToInterface(vpnId, vrfEntry.getDestPrefix());
+ String localNextHopIP = vrfEntry.getDestPrefix();
+
+ if(localNextHopInfo == null) {
+ //Is this fib route an extra route? If yes, get the nexthop which would be an adjacency in the vpn
+ Extraroute extra_route = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
+ if (extra_route != null) {
+ localNextHopInfo = getPrefixToInterface(vpnId, extra_route.getNexthopIp() + "/32");
+ localNextHopIP = extra_route.getNexthopIp() + "/32";
+ }
+ }
+
+ if(localNextHopInfo != null) {
+ localDpnId = localNextHopInfo.getDpnId();
+ long groupId = nextHopManager.createLocalNextHop(vpnId, localDpnId, localNextHopInfo.getVpnInterfaceName(), localNextHopIP);
+
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+
+ actionsInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId)}));
+ instructions.add(new InstructionInfo(InstructionType.write_actions,actionsInfos));
+ makeConnectedRoute(localDpnId, vpnId, vrfEntry, rd, instructions, NwConstants.ADD_FLOW);
+
+ actionsInfos=new ArrayList<ActionInfo>();;
+ instructions=new ArrayList<InstructionInfo>();
+ actionsInfos.add(new ActionInfo(ActionType.pop_mpls, new String[]{}));
+ actionsInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId) }));
+ instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos));
+ makeLFibTableEntry(localDpnId, vrfEntry.getLabel(), instructions, vrfEntry.getNextHopAddress(), NwConstants.ADD_FLOW);
+
+ LOG.debug("Installing tunnel table entry on dpn {} for interface {} with label {}",
+ localDpnId, localNextHopInfo.getVpnInterfaceName(), vrfEntry.getLabel());
+ makeTunnelTableEntry(localDpnId, vrfEntry.getLabel(), groupId);
+
+ }
+ return localDpnId;
+ }
+
+ private void makeTunnelTableEntry(BigInteger dpId, long label, long groupId/*String egressInterfaceName*/) {
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+ actionsInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId) }));
+
+
+ createTerminatingServiceActions(dpId, (int)label, actionsInfos);
+
+ LOG.debug("Terminating service Entry for dpID {} : label : {} egress : {} installed successfully {}",
+ dpId, label, groupId);
+ }
+
+ public void createTerminatingServiceActions( BigInteger destDpId, int label, List<ActionInfo> actionsInfos) {
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+
+ LOG.info("create terminatingServiceAction on DpnId = {} and serviceId = {} and actions = {}", destDpId , label,actionsInfos);
+
+ // Matching metadata
+ // FIXME vxlan vni bit set is not working properly with OVS.need to revisit
+ mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(label)}));
+
+ List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
+ mkInstructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos));
+
+ FlowEntity terminatingServiceTableFlowEntity = MDSALUtil.buildFlowEntity(destDpId, NwConstants.INTERNAL_TUNNEL_TABLE,
+ getFlowRef(destDpId, NwConstants.INTERNAL_TUNNEL_TABLE,label), 5, String.format("%s:%d","TST Flow Entry ",label),
+ 0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(label)),mkMatches, mkInstructions);
+
+ mdsalManager.installFlow(terminatingServiceTableFlowEntity);
+ }
+
+ private void removeTunnelTableEntry(BigInteger dpId, long label) {
+ FlowEntity flowEntity;
+ LOG.info("remove terminatingServiceActions called with DpnId = {} and label = {}", dpId , label);
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ // Matching metadata
+ mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(label)}));
+ flowEntity = MDSALUtil.buildFlowEntity(dpId,
+ NwConstants.INTERNAL_TUNNEL_TABLE,
+ getFlowRef(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, (int)label),
+ 5, String.format("%s:%d","TST Flow Entry ",label), 0, 0,
+ COOKIE_TUNNEL.add(BigInteger.valueOf(label)), mkMatches, null);
+ mdsalManager.removeFlow(flowEntity);
+ LOG.debug("Terminating service Entry for dpID {} : label : {} removed successfully {}",dpId, label);
+ }
+
+ public BigInteger deleteLocalFibEntry(Long vpnId, String rd, VrfEntry vrfEntry) {
+ BigInteger localDpnId = BigInteger.ZERO;
+ boolean isExtraRoute = false;
+ VpnNexthop localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, vrfEntry.getDestPrefix());
+ String localNextHopIP = vrfEntry.getDestPrefix();
+
+ if(localNextHopInfo == null) {
+ //Is this fib route an extra route? If yes, get the nexthop which would be an adjacency in the vpn
+ Extraroute extra_route = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
+ if (extra_route != null) {
+ localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, extra_route.getNexthopIp() + "/32");
+ localNextHopIP = extra_route.getNexthopIp() + "/32";
+ isExtraRoute = true;
+ }
+ }
+
+
+ if(localNextHopInfo != null) {
+ localDpnId = localNextHopInfo.getDpnId();
+ Prefixes prefix = getPrefixToInterface(vpnId, isExtraRoute ? localNextHopIP : vrfEntry.getDestPrefix());
+ makeConnectedRoute(localDpnId, vpnId, vrfEntry, rd, null /* invalid */,
+ NwConstants.DEL_FLOW);
+ makeLFibTableEntry(localDpnId, vrfEntry.getLabel(), null /* invalid */,
+ vrfEntry.getNextHopAddress(), NwConstants.DEL_FLOW);
+ removeTunnelTableEntry(localDpnId, vrfEntry.getLabel());
+ deleteLocalAdjacency(localDpnId, vpnId, localNextHopIP);
+ }
+ return localDpnId;
+ }
+
+ private InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(Long vpnId, String ipPrefix) {
+ return InstanceIdentifier.builder(PrefixToInterface.class)
+ .child(VpnIds.class, new VpnIdsKey(vpnId)).child(Prefixes.class, new PrefixesKey(ipPrefix)).build();
+ }
+
+ private Prefixes getPrefixToInterface(Long vpnId, String ipPrefix) {
+ Optional<Prefixes> localNextHopInfoData =
+ FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, getPrefixToInterfaceIdentifier(vpnId, ipPrefix));
+ return localNextHopInfoData.isPresent() ? localNextHopInfoData.get() : null;
+ }
+
+ private InstanceIdentifier<Extraroute> getVpnToExtrarouteIdentifier(String vrfId, String ipPrefix) {
+ return InstanceIdentifier.builder(VpnToExtraroute.class)
+ .child(Vpn.class, new VpnKey(vrfId)).child(Extraroute.class,
+ new ExtrarouteKey(ipPrefix)).build();
+ }
+
+ private Extraroute getVpnToExtraroute(String rd, String ipPrefix) {
+ Optional<Extraroute> extraRouteInfo =
+ FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, getVpnToExtrarouteIdentifier(rd, ipPrefix));
+ return extraRouteInfo.isPresent() ? extraRouteInfo.get() : null;
+
+ }
+
+ private Class<? extends TunnelTypeBase> getTunnelType(String ifName) {
+ try {
+ Future<RpcResult<GetTunnelTypeOutput>> result = interfaceManager.getTunnelType(
+ new GetTunnelTypeInputBuilder().setIntfName(ifName).build());
+ RpcResult<GetTunnelTypeOutput> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
+ } else {
+ return rpcResult.getResult().getTunnelType();
+ }
+
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when getting tunnel interface Id for tunnel type {}", e);
+ }
+
+ return null;
+
+ }
+ private void createRemoteFibEntry(final BigInteger localDpnId, final BigInteger remoteDpnId,
+ final long vpnId, final VrfTablesKey vrfTableKey,
+ final VrfEntry vrfEntry) {
+ String rd = vrfTableKey.getRouteDistinguisher();
+ LOG.debug("adding route " + vrfEntry.getDestPrefix() + " " + rd);
+ /********************************************/
+ String tunnelInterface = resolveAdjacency(localDpnId, remoteDpnId, vpnId, vrfEntry, rd);
+ if(tunnelInterface == null) {
+ LOG.error("Could not get interface for nexthop: {} in vpn {}",
+ vrfEntry.getNextHopAddress(), rd);
+ LOG.warn("Failed to add Route: {} in vpn: {}",
+ vrfEntry.getDestPrefix(), rd);
+ return;
+ }
+ List<ActionInfo> actionInfos = new ArrayList<>();
+ Class<? extends TunnelTypeBase> tunnel_type = getTunnelType(tunnelInterface);
+ if (tunnel_type.equals(TunnelTypeMplsOverGre.class)) {
+ LOG.debug("Push label action for prefix {}", vrfEntry.getDestPrefix());
+ actionInfos.add(new ActionInfo(ActionType.push_mpls, new String[] { null }));
+ actionInfos.add(new ActionInfo(ActionType.set_field_mpls_label, new String[] { Long.toString(vrfEntry.getLabel())}));
+ } else {
+ int label = vrfEntry.getLabel().intValue();
+ BigInteger tunnelId;
+ // FIXME vxlan vni bit set is not working properly with OVS.need to revisit
+ if(tunnel_type.equals(TunnelTypeVxlan.class)) {
+ tunnelId = BigInteger.valueOf(label);
+ } else {
+ tunnelId = BigInteger.valueOf(label);
+ }
+ LOG.debug("adding set tunnel id action for label {}", label);
+ actionInfos.add(new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[]{
+ tunnelId}));
+ }
+ actionInfos.addAll(nextHopManager.getEgressActionsForInterface(tunnelInterface));
+ List<InstructionInfo> instructions= new ArrayList<InstructionInfo>();
+ instructions.add(new InstructionInfo(InstructionType.write_actions, actionInfos));
+/*
+ List<ActionInfo> actionInfos = resolveAdjacency(localDpnId, remoteDpnId, vpnId, vrfEntry);
+ if(actionInfos == null) {
+ LOG.error("Could not get nexthop group id for nexthop: {} in vpn {}",
+ vrfEntry.getNextHopAddress(), rd);
+ LOG.warn("Failed to add Route: {} in vpn: {}",
+ vrfEntry.getDestPrefix(), rd);
+ return;
+ }
+ BigInteger dpnId = nextHopManager.getDpnForPrefix(vpnId, vrfEntry.getDestPrefix());
+ if(dpnId == null) {
+ //This route may be extra route... try to query with nexthop Ip
+ LOG.debug("Checking for extra route to install remote fib entry {}", vrfEntry.getDestPrefix());
+ dpnId = nextHopManager.getDpnForPrefix(vpnId, vrfEntry.getNextHopAddress() + "/32");
+ }
+ if(dpnId == null) {
+ LOG.debug("Push label action for prefix {}", vrfEntry.getDestPrefix());
+ actionInfos.add(new ActionInfo(ActionType.push_mpls, new String[] { null }));
+ actionInfos.add(new ActionInfo(ActionType.set_field_mpls_label, new String[] { Long.toString(vrfEntry.getLabel())}));
+ } else {
+ int label = vrfEntry.getLabel().intValue();
+ LOG.debug("adding set tunnel id action for label {}", label);
+ actionInfos.add(new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
+ MetaDataUtil.getTunnelIdWithValidVniBitAndVniSet(label),
+ MetaDataUtil.METADA_MASK_VALID_TUNNEL_ID_BIT_AND_TUNNEL_ID }));
+ }
+**/
+ makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, instructions, NwConstants.ADD_FLOW);
+ LOG.debug("Successfully added fib entry for " + vrfEntry.getDestPrefix() + " vpnId " + vpnId);
+ }
+
+ private void delIntfFromDpnToVpnList(long vpnId, BigInteger dpnId, String intfName, String rd) {
+ InstanceIdentifier<VpnToDpnList> id = FibUtil.getVpnToDpnListIdentifier(rd, dpnId);
+ Optional<VpnToDpnList> dpnInVpn = FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ if (dpnInVpn.isPresent()) {
+ List<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
+ .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
+ org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
+ currVpnInterface = new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesBuilder().setInterfaceName(intfName).build();
+
+ if (vpnInterfaces.remove(currVpnInterface)) {
+ if (vpnInterfaces.isEmpty()) {
+ LOG.trace("Last vpn interface {} on dpn {} for vpn {}. Clean up fib in dpn", intfName, dpnId, rd);
+ FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id);
+ cleanUpDpnForVpn(dpnId, vpnId, rd);
+ } else {
+ LOG.trace("Delete vpn interface {} from dpn {} to vpn {} list.", intfName, dpnId, rd);
+ FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id.child(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
+ .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey(intfName)));
+ }
+ }
+ }
+ }
+
+ private void cleanUpOpDataForFib(Long vpnId, String rd, final VrfEntry vrfEntry) {
+ /* Get interface info from prefix to interface mapping;
+ Use the interface info to get the corresponding vpn interface op DS entry,
+ remove the adjacency corresponding to this fib entry.
+ If adjacency removed is the last adjacency, clean up the following:
+ - vpn interface from dpntovpn list, dpn if last vpn interface on dpn
+ - prefix to interface entry
+ - vpn interface op DS
+ */
+ Prefixes prefixInfo = getPrefixToInterface(vpnId, vrfEntry.getDestPrefix());
+ Extraroute extraRoute = null;
+ if (prefixInfo == null) {
+ extraRoute = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
+ if(extraRoute != null) {
+ prefixInfo = getPrefixToInterface(vpnId, extraRoute.getNexthopIp() + "/32");
+ //clean up the vpn to extra route entry in DS
+ FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, FibUtil.getVpnToExtrarouteIdentifier(rd, vrfEntry.getDestPrefix()));
+ }
+ }
+ if (prefixInfo == null) {
+ LOG.debug("Cleanup VPN Data Failed as unable to find prefix Info for " + vrfEntry.getDestPrefix());
+ return; //Don't have any info for this prefix (shouldn't happen); need to return
+ }
+ String ifName = prefixInfo.getVpnInterfaceName();
+ Optional<Adjacencies> optAdjacencies = FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, FibUtil.getAdjListPath(ifName));
+ int numAdj = 0;
+ if (optAdjacencies.isPresent()) {
+ numAdj = optAdjacencies.get().getAdjacency().size();
+ }
+ LOG.trace("cleanUpOpDataForFib: remove adjacency for prefix: {} {}", vpnId, vrfEntry.getDestPrefix());
+ //remove adjacency corr to prefix
+ if (numAdj > 1) {
+ FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
+ FibUtil.getAdjacencyIdentifier(ifName, vrfEntry.getDestPrefix()));
+ }
+
+ if ((numAdj - 1) == 0) { //there are no adjacencies left for this vpn interface, clean up
+ //clean up the vpn interface from DpnToVpn list
+ LOG.trace("Clean up vpn interface {} from dpn {} to vpn {} list.", ifName, prefixInfo.getDpnId(), rd);
+ FibUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
+ FibUtil.getVpnInterfaceIdentifier(ifName));
+ }
+
+ FibUtil.releaseId(idManager, FibConstants.VPN_IDPOOL_NAME,
+ FibUtil.getNextHopLabelKey(rd, vrfEntry.getDestPrefix()));
+
+ }
+
+ private void deleteFibEntries(final InstanceIdentifier<VrfEntry> identifier,
+ final VrfEntry vrfEntry) {
+ final VrfTablesKey vrfTableKey = identifier.firstKeyOf(VrfTables.class, VrfTablesKey.class);
+ Preconditions.checkNotNull(vrfTableKey, "VrfTablesKey cannot be null or empty!");
+ Preconditions.checkNotNull(vrfEntry, "VrfEntry cannot be null or empty!");
+
+ String rd = vrfTableKey.getRouteDistinguisher();
+ VpnInstanceOpDataEntry vpnInstance = getVpnInstance(vrfTableKey.getRouteDistinguisher());
+ if (vpnInstance == null) {
+ LOG.debug("VPN Instance for rd {} is not available from VPN Op Instance Datastore", rd);
+ return;
+ }
+ Collection<VpnToDpnList> vpnToDpnList = vpnInstance.getVpnToDpnList();
+ RdToElanOpEntry rdToElanOpEntry= getRdToElanOpEntry(broker,vrfTableKey.getRouteDistinguisher(),
+ vrfEntry.getDestPrefix());
+ if (rdToElanOpEntry != null) {
+ if (vpnToDpnList!=null) {
+ for(VpnToDpnList curDpn : vpnToDpnList) {
+ makeConnectedRoute(curDpn.getDpnId(),vpnInstance.getVpnId(),vrfEntry,vrfTableKey
+ .getRouteDistinguisher(), null,NwConstants.DEL_FLOW);
+ makeLFibTableEntry(curDpn.getDpnId(),vrfEntry.getLabel(),null,
+ vrfEntry.getNextHopAddress(),NwConstants.DEL_FLOW);
+ // TODO DeleteTunnelTableEntry();
+ }
+ }
+ //Delete rd-to-elan-op-entry
+ InstanceIdentifier<RdToElanOpEntry> id = getRdToElanOpEntryDataPath(vrfTableKey.getRouteDistinguisher(),
+ vrfEntry.getDestPrefix());
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL,id);
+ FibUtil.releaseId(idManager,FibConstants.VPN_IDPOOL_NAME,
+ FibUtil.getNextHopLabelKey(rd, vrfEntry.getDestPrefix()));
+ return;
+ }
+ BigInteger localDpnId = deleteLocalFibEntry(vpnInstance.getVpnId(),
+ vrfTableKey.getRouteDistinguisher(), vrfEntry);
+ if (vpnToDpnList != null) {
+ for (VpnToDpnList curDpn : vpnToDpnList) {
+ if (!curDpn.getDpnId().equals(localDpnId)) {
+ deleteRemoteRoute(localDpnId, curDpn.getDpnId(), vpnInstance.getVpnId(), vrfTableKey, vrfEntry);
+ }
+ }
+ }
+ //The flow/group entry has been deleted from config DS; need to clean up associated operational
+ //DS entries in VPN Op DS, VpnInstanceOpData and PrefixToInterface to complete deletion
+ cleanUpOpDataForFib(vpnInstance.getVpnId(), vrfTableKey.getRouteDistinguisher(), vrfEntry);
+ }
+
+ public void deleteRemoteRoute(final BigInteger localDpnId, final BigInteger remoteDpnId,
+ final long vpnId, final VrfTablesKey vrfTableKey,
+ final VrfEntry vrfEntry) {
+ LOG.debug("deleting route "+ vrfEntry.getDestPrefix() + " "+vpnId);
+ String rd = vrfTableKey.getRouteDistinguisher();
+ boolean isRemoteRoute = true;
+ if (localDpnId == null) {
+ // localDpnId is not known when clean up happens for last vm for a vpn on a dpn
+ VpnNexthop localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, vrfEntry.getDestPrefix());
+ if(localNextHopInfo == null) {
+ //Is this fib route an extra route? If yes, get the nexthop which would be an adjacency in the vpn
+ Extraroute extra_route = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
+ if (extra_route != null) {
+ localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, extra_route.getNexthopIp());
+ }
+ }
+ if (localNextHopInfo != null) {
+ isRemoteRoute = (!remoteDpnId.equals(localNextHopInfo.getDpnId()));
+ }
+ }
+ if (isRemoteRoute) {
+ makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, null, NwConstants.DEL_FLOW);
+ LOG.debug("Successfully delete fib entry for "+ vrfEntry.getDestPrefix() + " vpnId "+vpnId);
+ } else{
+ LOG.debug("Did not delete fib entry rd: {} =, prefix: {} as it is local to dpn {}", rd, vrfEntry.getDestPrefix(), remoteDpnId);
+ }
+ }
+
+ private long getIpAddress(byte[] rawIpAddress) {
+ return (((rawIpAddress[0] & 0xFF) << (3 * 8)) + ((rawIpAddress[1] & 0xFF) << (2 * 8))
+ + ((rawIpAddress[2] & 0xFF) << (1 * 8)) + (rawIpAddress[3] & 0xFF)) & 0xffffffffL;
+ }
+
+ private void makeConnectedRoute(BigInteger dpId, long vpnId, VrfEntry vrfEntry, String rd,
+ List<InstructionInfo> instructions, int addOrRemove) { LOG.trace("makeConnectedRoute: vrfEntry {}",vrfEntry);
+ String values[] = vrfEntry.getDestPrefix().split("/");
+ String ipAddress = values[0];
+ int prefixLength = (values.length == 1) ? 0 : Integer.parseInt(values[1]);
+ LOG.debug("Adding route to DPN. ip {} masklen {}", ipAddress, prefixLength);
+ InetAddress destPrefix = null;
+ try {
+ destPrefix = InetAddress.getByName(ipAddress);
+ } catch (UnknownHostException e) {
+ LOG.error("UnknowHostException in addRoute. Failed to add Route for ipPrefix {}", vrfEntry.getDestPrefix());
+ return;
+ }
+
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
+
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+
+ if(prefixLength != 0) {
+ matches.add(new MatchInfo(MatchFieldType.ipv4_destination, new String[] {
+ destPrefix.getHostAddress(), Integer.toString(prefixLength)}));
+ }
+
+ String flowRef = getFlowRef(dpId, NwConstants.L3_FIB_TABLE, rd, destPrefix);
+
+ FlowEntity flowEntity;
+
+ int priority = DEFAULT_FIB_FLOW_PRIORITY + prefixLength;
+ flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_FIB_TABLE, flowRef,
+ priority, flowRef, 0, 0,
+ COOKIE_VM_FIB_TABLE, matches, instructions);
+
+ if (addOrRemove == NwConstants.ADD_FLOW) {
+ /* We need to call sync API to install flow so that 2 DS operations on the same object do not
+ * happen at same time. However, MDSALManager's syncInstallFlow takes a delay time (or uses a default one) to wait
+ * for or for notification that operational DS write for flows is done. We do not turn on the stats writing for flows,
+ * so that notification never comes, so we do not need that wait. Sending the lowest value of wait "1 ms" since 0 wait means
+ * wait indefinitely. */
+ mdsalManager.syncInstallFlow(flowEntity, 1);
+ } else {
+ mdsalManager.syncRemoveFlow(flowEntity, 1);
+ }
+ }
+
+ private void makeLFibTableEntry(BigInteger dpId, long label, List<InstructionInfo> instructions,
+ String nextHop, int addOrRemove) {
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x8847L }));
+ matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(label)}));
+
+ // Install the flow entry in L3_LFIB_TABLE
+ String flowRef = getFlowRef(dpId, NwConstants.L3_LFIB_TABLE, label, nextHop);
+
+ FlowEntity flowEntity;
+ flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_LFIB_TABLE, flowRef,
+ DEFAULT_FIB_FLOW_PRIORITY, flowRef, 0, 0,
+ COOKIE_VM_LFIB_TABLE, matches, instructions);
+
+ if (addOrRemove == NwConstants.ADD_FLOW) {
+ /* We need to call sync API to install flow so that 2 DS operations on the same object do not
+ * happen at same time. However, MDSALManager's syncInstallFlow takes a delay time (or uses a default one) to wait
+ * for or for notification that operational DS write for flows is done. We do not turn on the stats writing for flows,
+ * so that notification never comes, so we do not need that wait. Sending the lowest value of wait "1 ms" since 0 wait means
+ * wait indefinitely. */
+
+ mdsalManager.syncInstallFlow(flowEntity, 1);
+ } else {
+ mdsalManager.syncRemoveFlow(flowEntity, 1);
+ }
+ LOG.debug("LFIB Entry for dpID {} : label : {} instructions {} modified successfully {}",dpId, label, instructions );
+ }
+
+ private void deleteLocalAdjacency(final BigInteger dpId, final long vpnId, final String ipAddress) {
+ LOG.trace("deleteLocalAdjacency called with dpid {}, vpnId{}, ipAddress {}",dpId, vpnId, ipAddress);
+ try {
+ nextHopManager.removeLocalNextHop(dpId, vpnId, ipAddress);
+ } catch (NullPointerException e) {
+ LOG.trace("", e);
+ }
+ }
+
+ public void populateFibOnNewDpn(BigInteger dpnId, long vpnId, String rd) {
+ LOG.trace("New dpn {} for vpn {} : populateFibOnNewDpn", dpnId, rd);
+ InstanceIdentifier<VrfTables> id = buildVrfId(rd);
+ String lockOnDpnVpn = new String(dpnId.toString()+ vpnId);
+ synchronized (lockOnDpnVpn.intern()) {
+ Optional<VrfTables> vrfTable = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
+ if (vrfTable.isPresent()) {
+ for (VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
+ RdToElanOpEntry rdToElanOpEntry = getRdToElanOpEntry(broker, rd,
+ vrfEntry.getDestPrefix());
+ if (rdToElanOpEntry!= null) {
+ installSubnetRouteInFib(dpnId, rdToElanOpEntry, vpnId, vrfEntry);
+ continue;
+ }
+ // Passing null as we don't know the dpn
+ // to which prefix is attached at this point
+ createRemoteFibEntry(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
+ }
+ }
+ }
+ }
+
+ public void populateFibOnDpn(BigInteger dpnId, long vpnId, String rd, String nexthopIp) {
+ LOG.trace("dpn {} for vpn {}, nexthopIp {} : populateFibOnDpn", dpnId, rd, nexthopIp);
+ InstanceIdentifier<VrfTables> id = buildVrfId(rd);
+ String lockOnDpnVpn = new String(dpnId.toString()+ vpnId);
+ synchronized (lockOnDpnVpn.intern()) {
+ Optional<VrfTables> vrfTable = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
+ if (vrfTable.isPresent()) {
+ for (VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
+ // Passing null as we don't know the dpn
+ // to which prefix is attached at this point
+ if (nexthopIp == vrfEntry.getNextHopAddress()) {
+ createRemoteFibEntry(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
+ }
+ }
+ }
+ }
+ }
+
+ public void cleanUpDpnForVpn(BigInteger dpnId, long vpnId, String rd) {
+ LOG.trace("Remove dpn {} for vpn {} : cleanUpDpnForVpn", dpnId, rd);
+ InstanceIdentifier<VrfTables> id = buildVrfId(rd);
+ String lockOnDpnVpn = new String(dpnId.toString()+ vpnId);
+ synchronized (lockOnDpnVpn.intern()) {
+ Optional<VrfTables> vrfTable = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
+ if (vrfTable.isPresent()) {
+ for (VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
+ /* Handle subnet routes here */
+ RdToElanOpEntry rdToElanOpEntry= getRdToElanOpEntry(broker, rd,
+ vrfEntry.getDestPrefix());
+ if (rdToElanOpEntry != null) {
+ LOG.trace("Cleaning subnetroute {} on dpn {} for vpn {} : cleanUpDpnForVpn", vrfEntry.getDestPrefix(),
+ dpnId, rd);
+ makeConnectedRoute(dpnId, vpnId, vrfEntry, rd, null, NwConstants.DEL_FLOW);
+ makeLFibTableEntry(dpnId, vrfEntry.getLabel(), null,
+ vrfEntry.getNextHopAddress(),NwConstants.DEL_FLOW);
+ continue;
+ }
+ // Passing null as we don't know the dpn
+ // to which prefix is attached at this point
+ deleteRemoteRoute(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
+ }
+ }
+ }
+ }
+
+ public void cleanUpDpnForVpn(BigInteger dpnId, long vpnId, String rd, String nexthopIp) {
+ LOG.trace("dpn {} for vpn {}, nexthopIp {} : cleanUpDpnForVpn", dpnId, rd, nexthopIp);
+ InstanceIdentifier<VrfTables> id = buildVrfId(rd);
+ String lockOnDpnVpn = new String(dpnId.toString()+ vpnId);
+ synchronized (lockOnDpnVpn.intern()) {
+ Optional<VrfTables> vrfTable = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
+ if (vrfTable.isPresent()) {
+ for (VrfEntry vrfEntry : vrfTable.get().getVrfEntry()) {
+ // Passing null as we don't know the dpn
+ // to which prefix is attached at this point
+ if (nexthopIp == vrfEntry.getNextHopAddress()) {
+ deleteRemoteRoute(null, dpnId, vpnId, vrfTable.get().getKey(), vrfEntry);
+ }
+ }
+ }
+ }
+ }
+
+ public static InstanceIdentifier<VrfTables> buildVrfId(String rd) {
+ InstanceIdentifierBuilder<VrfTables> idBuilder =
+ InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
+ InstanceIdentifier<VrfTables> id = idBuilder.build();
+ return id;
+ }
+
+ private String getFlowRef(BigInteger dpnId, short tableId, long label, String nextHop) {
+ return new StringBuilder(64).append(FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
+ .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
+ .append(label).append(NwConstants.FLOWID_SEPARATOR)
+ .append(nextHop).toString();
+ }
+
+ private String getFlowRef(BigInteger dpnId, short tableId, String rd, InetAddress destPrefix) {
+ return new StringBuilder(64).append(FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
+ .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
+ .append(rd).append(NwConstants.FLOWID_SEPARATOR)
+ .append(destPrefix.getHostAddress()).toString();
+ }
+
+ protected String resolveAdjacency(final BigInteger localDpnId, final BigInteger remoteDpnId,
+ final long vpnId, final VrfEntry vrfEntry, String rd) {
+ String adjacency = null;
+ boolean staticRoute = false;
+ LOG.trace("resolveAdjacency called with localdpid{} remotedpid {}, vpnId{}, VrfEntry {}", localDpnId, remoteDpnId, vpnId, vrfEntry);
+ try {
+ Extraroute extra_route = getVpnToExtraroute(rd, vrfEntry.getDestPrefix());
+ if(extra_route != null) {
+ staticRoute = true;
+ }
+
+ adjacency =
+ nextHopManager.getRemoteNextHopPointer(localDpnId, remoteDpnId, vpnId,
+ (staticRoute == true) ? extra_route.getNexthopIp() + "/32" : vrfEntry.getDestPrefix(),
+ vrfEntry.getNextHopAddress());
+ } catch (NullPointerException e) {
+ LOG.trace("", e);
+ }
+ return adjacency;
+ }
+
+ protected VpnInstanceOpDataEntry getVpnInstance(String rd) {
+ InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.create(VpnInstanceOpData.class).child(
+ VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd));
+ Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = FibUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ if(vpnInstanceOpData.isPresent()) {
+ return vpnInstanceOpData.get();
+ }
+ return null;
+ }
+
+ public void processNodeAdd(BigInteger dpnId) {
+ LOG.debug("Received notification to install TableMiss entries for dpn {} ", dpnId);
+ makeTableMissFlow(dpnId, NwConstants.ADD_FLOW);
+ makeL3IntfTblMissFlow(dpnId, NwConstants.ADD_FLOW);
+ makeSubnetRouteTableMissFlow(dpnId, NwConstants.ADD_FLOW);
+ }
+
+ private void makeTableMissFlow(BigInteger dpnId, int addOrRemove) {
+ final BigInteger COOKIE_TABLE_MISS = new BigInteger("1030000", 16);
+ // Instruction to goto L3 InterfaceTable
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.L3_INTERFACE_TABLE }));
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ FlowEntity flowEntityLfib = MDSALUtil.buildFlowEntity(dpnId, NwConstants.L3_LFIB_TABLE,
+ getFlowRef(dpnId, NwConstants.L3_LFIB_TABLE, NwConstants.TABLE_MISS_FLOW),
+ NwConstants.TABLE_MISS_PRIORITY, "Table Miss", 0, 0, COOKIE_TABLE_MISS, matches, instructions);
+
+ FlowEntity flowEntityFib = MDSALUtil.buildFlowEntity(dpnId,NwConstants.L3_FIB_TABLE, getFlowRef(dpnId, NwConstants.L3_FIB_TABLE, NwConstants.TABLE_MISS_FLOW),
+ NwConstants.TABLE_MISS_PRIORITY, "FIB Table Miss Flow", 0, 0, COOKIE_VM_FIB_TABLE,
+ matches, instructions);
+
+ if (addOrRemove == NwConstants.ADD_FLOW) {
+ LOG.debug("Invoking MDSAL to install Table Miss Entries");
+ mdsalManager.installFlow(flowEntityLfib);
+ mdsalManager.installFlow(flowEntityFib);
+ } else {
+ mdsalManager.removeFlow(flowEntityLfib);
+ mdsalManager.removeFlow(flowEntityFib);
+
+ }
+ }
+
+ private String getFlowRef(BigInteger dpnId, short tableId, int tableMiss) {
+ return new StringBuffer().append(FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
+ .append(tableId).append(NwConstants.FLOWID_SEPARATOR).append(tableMiss)
+ .append(FLOWID_PREFIX).toString();
+ }
+
+ /*
+ * Install flow entry in protocol table to forward mpls
+ * coming through gre tunnel to LFIB table.
+ */
+ private void makeProtocolTableFlow(BigInteger dpnId, int addOrRemove) {
+ final BigInteger COOKIE_PROTOCOL_TABLE = new BigInteger("1070000", 16);
+ // Instruction to goto L3 InterfaceTable
+ List<InstructionInfo> instructions = new ArrayList<>();
+ instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] {NwConstants.L3_LFIB_TABLE}));
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x8847L }));
+ FlowEntity flowEntityToLfib = MDSALUtil.buildFlowEntity(dpnId, NwConstants.L3_PROTOCOL_TABLE,
+ getFlowRef(dpnId, NwConstants.L3_PROTOCOL_TABLE,
+ NwConstants.L3_LFIB_TABLE),
+ DEFAULT_FIB_FLOW_PRIORITY,
+ "Protocol Table For LFIB",
+ 0, 0,
+ COOKIE_PROTOCOL_TABLE,
+ matches, instructions);
+
+ if (addOrRemove == NwConstants.ADD_FLOW) {
+ LOG.debug("Invoking MDSAL to install Protocol Entries for dpn {}", dpnId);
+ mdsalManager.installFlow(flowEntityToLfib);
+ } else {
+ mdsalManager.removeFlow(flowEntityToLfib);
+ }
+ }
+
+ public List<String> printFibEntries() {
+ List<String> result = new ArrayList<String>();
+ result.add(String.format(" %-7s %-20s %-20s %-7s", "RD", "Prefix", "Nexthop", "Label"));
+ result.add("-------------------------------------------------------------------");
+ InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
+ Optional<FibEntries> fibEntries = FibUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
+ if (fibEntries.isPresent()) {
+ List<VrfTables> vrfTables = fibEntries.get().getVrfTables();
+ for (VrfTables vrfTable : vrfTables) {
+ for (VrfEntry vrfEntry : vrfTable.getVrfEntry()) {
+ result.add(String.format(" %-7s %-20s %-20s %-7s", vrfTable.getRouteDistinguisher(),
+ vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddress(), vrfEntry.getLabel()));
+ }
+ }
+ }
+ return result;
+ }
+
+ private void makeL3IntfTblMissFlow(BigInteger dpnId, int addOrRemove) {
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ final BigInteger COOKIE_TABLE_MISS = new BigInteger("1030000", 16);
+ // Instruction to clear metadata except SI and LportTag bits
+ instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] {
+ CLEAR_METADATA, METADATA_MASK_CLEAR }));
+ // Instruction to clear action
+ instructions.add(new InstructionInfo(InstructionType.clear_actions));
+ // Instruction to goto L3 InterfaceTable
+
+ List <ActionInfo> actionsInfos = new ArrayList <ActionInfo> ();
+ actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[]{
+ Short.toString(NwConstants.LPORT_DISPATCHER_TABLE)}));
+ instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+ //instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.LPORT_DISPATCHER_TABLE }));
+
+ FlowEntity flowEntityL3Intf = MDSALUtil.buildFlowEntity(dpnId, NwConstants.L3_INTERFACE_TABLE,
+ getFlowRef(dpnId, NwConstants.L3_INTERFACE_TABLE, NwConstants.TABLE_MISS_FLOW),
+ NwConstants.TABLE_MISS_PRIORITY, "L3 Interface Table Miss", 0, 0, COOKIE_TABLE_MISS, matches, instructions);
+ if (addOrRemove == NwConstants.ADD_FLOW) {
+ LOG.info("Invoking MDSAL to install L3 interface Table Miss Entries");
+ mdsalManager.installFlow(flowEntityL3Intf);
+ } else {
+ mdsalManager.removeFlow(flowEntityL3Intf);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.fibmanager;
+
+import java.math.BigInteger;
+import java.util.List;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RpcRegistration;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.fibmanager.api.IFibManager;
+import org.opendaylight.vpnmanager.api.IVpnManager;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.FibRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FibManagerProvider implements BindingAwareProvider, IFibManager, AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(FibManagerProvider.class);
+
+ private FibManager fibManager;
+ private IMdsalApiManager mdsalManager;
+ private IVpnManager vpnmanager;
+ private NexthopManager nexthopManager;
+ private IdManagerService idManager;
+ private ItmRpcService itmManager;
+ private OdlInterfaceRpcService interfaceManager;
+ private FibNodeCapableListener fibNcListener;
+ private RpcProviderRegistry rpcProviderRegistry;
+ private RpcRegistration<FibRpcService> rpcRegistration;
+
+ @Override
+ public void onSessionInitiated(ProviderContext session) {
+ LOG.info("FibManagerProvider Session Initiated");
+ try {
+ final DataBroker dataBroker = session.getSALService(DataBroker.class);
+ nexthopManager = new NexthopManager(dataBroker);
+ nexthopManager.setMdsalManager(mdsalManager);
+ nexthopManager.setIdManager(idManager);
+ nexthopManager.setInterfaceManager(interfaceManager);
+ nexthopManager.setITMRpcService(itmManager);
+ fibManager = new FibManager(dataBroker);
+ fibManager.setMdsalManager(mdsalManager);
+ fibManager.setVpnmanager(vpnmanager);
+ fibManager.setNextHopManager(nexthopManager);
+ fibManager.setITMRpcService(itmManager);
+ fibManager.setInterfaceManager(interfaceManager);
+ fibManager.setIdManager(idManager);
+ fibNcListener = new FibNodeCapableListener(dataBroker, fibManager);
+ FibRpcService fibRpcService = new FibRpcServiceImpl(dataBroker, mdsalManager, this);
+ rpcRegistration = getRpcProviderRegistry().addRpcImplementation(FibRpcService.class, fibRpcService);
+ } catch (Exception e) {
+ LOG.error("Error initializing services", e);
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ LOG.info("FibManagerProvider Closed");
+ fibManager.close();
+ fibNcListener.close();
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ public void setVpnmanager(IVpnManager vpnmanager) {
+ this.vpnmanager = vpnmanager;
+ vpnmanager.setFibService(this);
+ }
+
+ public void setIdManager(IdManagerService idManager) {
+ this.idManager = idManager;
+ }
+
+ public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
+ this.interfaceManager = interfaceManager;
+ }
+
+ public void setITMProvider(ItmRpcService itmManager) {
+ this.itmManager = itmManager;
+ }
+
+ @Override
+ public void populateFibOnNewDpn(BigInteger dpnId, long vpnId, String rd) {
+ fibManager.populateFibOnNewDpn(dpnId, vpnId, rd);
+ }
+
+ @Override
+ public void cleanUpDpnForVpn(BigInteger dpnId, long vpnId, String rd) {
+ fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
+ }
+
+ @Override
+ public List<String> printFibEntries() {
+ return fibManager.printFibEntries();
+ }
+
+ //Temp
+ @Override
+ public void addStaticRoute(String prefix, String nextHop, String rd, int label) {
+ this.vpnmanager.addExtraRoute(prefix, nextHop, rd, null, label);
+ }
+
+ @Override
+ public void deleteStaticRoute(String prefix, String rd) {
+ this.vpnmanager.delExtraRoute(prefix, rd, null);
+ }
+
+ public void setRpcProviderRegistry(RpcProviderRegistry rpcProviderRegistry) {
+ this.rpcProviderRegistry = rpcProviderRegistry;
+ }
+
+ private RpcProviderRegistry getRpcProviderRegistry() {
+ return rpcProviderRegistry;
+ }
+
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.vpnservice.fibmanager;
+
+import java.math.BigInteger;
+
+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.mdsalutil.MDSALUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+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.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FibNodeCapableListener extends AbstractDataChangeListener<FlowCapableNode> implements AutoCloseable{
+ private static final Logger LOG = LoggerFactory.getLogger(FibNodeCapableListener.class);
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private FibManager fibManager;
+
+ public FibNodeCapableListener(final DataBroker dataBroker, FibManager fibManager) {
+ super(FlowCapableNode.class);
+ registerListener(dataBroker);
+ this.fibManager = fibManager;
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), FibNodeCapableListener.this, DataChangeScope.ONE);
+ } catch (final Exception e) {
+ LOG.error("FibNodeConnectorListener: DataChange listener registration fail!", e);
+ throw new IllegalStateException("FibNodeConnectorListener: registration Listener failed.", e);
+ }
+ }
+
+ private InstanceIdentifier<FlowCapableNode> getWildCardPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class).augmentation(FlowCapableNode.class);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("FibNodeConnectorListener Closed");
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<FlowCapableNode> identifier, FlowCapableNode node) {
+ LOG.trace("FlowCapableNode Added: key: " + identifier + ", value=" + node );
+ NodeKey nodeKey = identifier.firstKeyOf(Node.class, NodeKey.class);
+ BigInteger dpnId = MDSALUtil.getDpnIdFromNodeName(nodeKey.getId());
+ fibManager.processNodeAdd(dpnId);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<FlowCapableNode> identifier, FlowCapableNode del) {
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<FlowCapableNode> identifier, FlowCapableNode original, FlowCapableNode update) {
+ }
+}
--- /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.fibmanager;
+
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.fibmanager.api.IFibManager;
+import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.ActionType;
+import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
+import org.opendaylight.vpnservice.mdsalutil.InstructionType;
+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.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceToVpnId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddressesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddressesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.CreateFibEntryInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.RemoveFibEntryInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.FibRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
+import static org.opendaylight.vpnservice.fibmanager.FibConstants.*;
+
+public class FibRpcServiceImpl implements FibRpcService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(FibRpcServiceImpl.class);
+ private IMdsalApiManager mdsalManager;
+ private DataBroker broker;
+ private IFibManager fibManager;
+
+ public FibRpcServiceImpl(DataBroker broker, IMdsalApiManager mdsalManager, IFibManager fibManager) {
+ this.broker = broker;
+ this.mdsalManager = mdsalManager;
+ this.fibManager = fibManager;
+ }
+
+
+ /**
+ * to install FIB routes on specified dpn with given instructions
+ *
+ */
+ public Future<RpcResult<Void>> createFibEntry(CreateFibEntryInput input) {
+
+ BigInteger dpnId = input.getSourceDpid();
+ String vpnName = input.getVpnName();
+ long vpnId = getVpnId(broker, vpnName);
+ String ipAddress = input.getIpAddress();
+ LOG.info("Create custom FIB entry - {} on dpn {} for VPN {} ", ipAddress, dpnId, vpnName);
+ List<Instruction> instructions = input.getInstruction();
+
+ makeLocalFibEntry(vpnId, dpnId, ipAddress, instructions);
+ updateVpnToDpnAssociation(vpnId, dpnId, ipAddress, vpnName);
+
+ return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
+ }
+
+ /**
+ * to remove FIB/LFIB/TST routes from specified dpn
+ *
+ */
+ public Future<RpcResult<Void>> removeFibEntry(RemoveFibEntryInput input) {
+
+ BigInteger dpnId = input.getSourceDpid();
+ String vpnName = input.getVpnName();
+ long vpnId = getVpnId(broker, vpnName);
+ long serviceId = input.getServiceId();
+ String ipAddress = input.getIpAddress();
+
+ LOG.info("Delete custom FIB entry - {} on dpn {} for VPN {} ", ipAddress, dpnId, vpnName);
+
+ removeLocalFibEntry(dpnId, vpnId, ipAddress);
+ //removeLFibTableEntry(dpnId, serviceId);
+ //removeTunnelTableEntry(dpnId, serviceId);
+ removeFromVpnDpnAssociation(vpnId, dpnId, ipAddress, vpnName);
+
+ return Futures.immediateFuture(RpcResultBuilder.<Void>success().build());
+ }
+
+ private void removeLocalFibEntry(BigInteger dpnId, long vpnId, String ipPrefix) {
+ String values[] = ipPrefix.split("/");
+ String ipAddress = values[0];
+ int prefixLength = (values.length == 1) ? 0 : Integer.parseInt(values[1]);
+ LOG.debug("Removing route from DPN. ip {} masklen {}", ipAddress, prefixLength);
+ InetAddress destPrefix = null;
+ try {
+ destPrefix = InetAddress.getByName(ipAddress);
+ } catch (UnknownHostException e) {
+ LOG.error("UnknowHostException in removeRoute. Failed to remove Route for ipPrefix {}", ipAddress);
+ return;
+ }
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
+
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+
+ if(prefixLength != 0) {
+ matches.add(new MatchInfo(MatchFieldType.ipv4_destination, new String[] {
+ destPrefix.getHostAddress(), Integer.toString(prefixLength) }));
+ }
+
+ String flowRef = getFlowRef(dpnId, NwConstants.L3_FIB_TABLE, vpnId, ipAddress);
+
+
+ int priority = DEFAULT_FIB_FLOW_PRIORITY + prefixLength;
+ Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_FIB_TABLE, flowRef,
+ priority, flowRef, 0, 0,
+ COOKIE_VM_FIB_TABLE, matches, null);
+
+ mdsalManager.removeFlow(dpnId, flowEntity);
+
+ LOG.debug("FIB entry for route {} on dpn {} removed successfully", ipAddress, dpnId);
+ }
+
+ private void removeLFibTableEntry(BigInteger dpnId, long serviceId) {
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x8847L }));
+ matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
+
+ String flowRef = getFlowRef(dpnId, NwConstants.L3_LFIB_TABLE, serviceId, "");
+
+ LOG.debug("removing LFib entry with flow ref {}", flowRef);
+
+ Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
+ DEFAULT_FIB_FLOW_PRIORITY, flowRef, 0, 0,
+ COOKIE_VM_LFIB_TABLE, matches, null);
+
+ mdsalManager.removeFlow(dpnId, flowEntity);
+
+ LOG.debug("LFIB Entry for dpID : {} label : {} removed successfully {}",dpnId, serviceId);
+ }
+
+ private void removeTunnelTableEntry(BigInteger dpnId, long serviceId) {
+ LOG.info("remove terminatingServiceActions called with DpnId = {} and label = {}", dpnId , serviceId);
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ // Matching metadata
+ mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
+ Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
+ getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""),
+ 5, String.format("%s:%d","TST Flow Entry ",serviceId), 0, 0,
+ COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, null);
+ mdsalManager.removeFlow(dpnId, flowEntity);
+ LOG.debug("Terminating service Entry for dpID {} : label : {} removed successfully {}",dpnId, serviceId);
+ }
+
+ private void makeTunnelTableEntry(BigInteger dpnId, long serviceId, List<Instruction> customInstructions) {
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+
+ LOG.info("create terminatingServiceAction on DpnId = {} and serviceId = {} and actions = {}", dpnId , serviceId);
+
+ mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
+
+ Flow terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
+ getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""), 5, String.format("%s:%d","TST Flow Entry ",serviceId),
+ 0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)),mkMatches, customInstructions);
+
+ mdsalManager.installFlow(dpnId, terminatingServiceTableFlowEntity);
+ }
+
+ private long getIpAddress(byte[] rawIpAddress) {
+ return (((rawIpAddress[0] & 0xFF) << (3 * 8)) + ((rawIpAddress[1] & 0xFF) << (2 * 8))
+ + ((rawIpAddress[2] & 0xFF) << (1 * 8)) + (rawIpAddress[3] & 0xFF)) & 0xffffffffL;
+ }
+
+ private void makeLocalFibEntry(long vpnId, BigInteger dpnId, String ipPrefix, List<Instruction> customInstructions) {
+ String values[] = ipPrefix.split("/");
+ String ipAddress = values[0];
+ int prefixLength = (values.length == 1) ? 0 : Integer.parseInt(values[1]);
+ LOG.debug("Adding route to DPN. ip {} masklen {}", ipAddress, prefixLength);
+ InetAddress destPrefix = null;
+ try {
+ destPrefix = InetAddress.getByName(ipAddress);
+ } catch (UnknownHostException e) {
+ LOG.error("UnknowHostException in addRoute. Failed to add Route for ipPrefix {}", ipAddress);
+ return;
+ }
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
+
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+
+ if(prefixLength != 0) {
+ matches.add(new MatchInfo(MatchFieldType.ipv4_destination, new String[] {
+ destPrefix.getHostAddress(), Integer.toString(prefixLength) }));
+ }
+
+ String flowRef = getFlowRef(dpnId, NwConstants.L3_FIB_TABLE, vpnId, ipAddress);
+
+
+ int priority = DEFAULT_FIB_FLOW_PRIORITY + prefixLength;
+ Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_FIB_TABLE, flowRef,
+ priority, flowRef, 0, 0,
+ COOKIE_VM_FIB_TABLE, matches, customInstructions);
+
+ mdsalManager.installFlow(dpnId, flowEntity);
+
+ LOG.debug("FIB entry for route {} on dpn {} installed successfully", ipAddress, dpnId);
+ }
+
+ private void makeLFibTableEntry(BigInteger dpId, long serviceId, List<Instruction> customInstructions) {
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x8847L }));
+ matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
+
+ List<Instruction> instructions = new ArrayList<Instruction>();
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+ actionsInfos.add(new ActionInfo(ActionType.pop_mpls, new String[]{}));
+ Instruction writeInstruction = new InstructionInfo(InstructionType.write_actions, actionsInfos).buildInstruction(0);
+ instructions.add(writeInstruction);
+ instructions.addAll(customInstructions);
+
+ // Install the flow entry in L3_LFIB_TABLE
+ String flowRef = getFlowRef(dpId, NwConstants.L3_LFIB_TABLE, serviceId, "");
+
+ Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
+ DEFAULT_FIB_FLOW_PRIORITY, flowRef, 0, 0,
+ COOKIE_VM_LFIB_TABLE, matches, instructions);
+
+ mdsalManager.installFlow(dpId, flowEntity);
+
+ LOG.debug("LFIB Entry for dpID {} : label : {} modified successfully {}",dpId, serviceId );
+ }
+
+ private String getFlowRef(BigInteger dpnId, short tableId, long id, String ipAddress) {
+ return new StringBuilder(64).append(FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
+ .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
+ .append(id).append(NwConstants.FLOWID_SEPARATOR).append(ipAddress).toString();
+ }
+
+ private synchronized void updateVpnToDpnAssociation(long vpnId, BigInteger dpnId, String ipAddr, String vpnName) {
+ LOG.debug("Updating VPN to DPN list for dpn : {} for VPN: {} with ip: {}",
+ dpnId, vpnName, ipAddr);
+ String routeDistinguisher = getVpnRd(broker, vpnName);
+ String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
+ InstanceIdentifier<VpnToDpnList> id = getVpnToDpnListIdentifier(rd, dpnId);
+ Optional<VpnToDpnList> dpnInVpn = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses
+ ipAddress = new IpAddressesBuilder().setIpAddress(ipAddr).build();
+
+ if (dpnInVpn.isPresent()) {
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id.child(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance
+ .op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses.class,
+ new IpAddressesKey(ipAddr)), ipAddress);
+ } else {
+ MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
+ getVpnInstanceOpDataIdentifier(rd),
+ getVpnInstanceOpData(rd, vpnId));
+ VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId);
+ List<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
+ .vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses> ipAddresses = new ArrayList<>();
+ ipAddresses.add(ipAddress);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id,
+ vpnToDpnList.setIpAddresses(ipAddresses).build());
+ LOG.debug("populate FIB on new dpn {} for VPN {}", dpnId, vpnName);
+ fibManager.populateFibOnNewDpn(dpnId, vpnId, rd);
+ }
+ }
+
+ private synchronized void removeFromVpnDpnAssociation(long vpnId, BigInteger dpnId, String ipAddr, String vpnName) {
+ LOG.debug("Removing association of VPN to DPN list for dpn : {} for VPN: {} with ip: {}",
+ dpnId, vpnName, ipAddr);
+ String routeDistinguisher = getVpnRd(broker, vpnName);
+ String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
+ InstanceIdentifier<VpnToDpnList> id = getVpnToDpnListIdentifier(rd, dpnId);
+ Optional<VpnToDpnList> dpnInVpn = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ if (dpnInVpn.isPresent()) {
+ List<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
+ .vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses> ipAddresses = dpnInVpn.get().getIpAddresses();
+ org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses
+ ipAddress = new IpAddressesBuilder().setIpAddress(ipAddr).build();
+
+ if (ipAddresses != null && ipAddresses.remove(ipAddress)) {
+ if (ipAddresses.isEmpty()) {
+ List<VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
+ if(vpnInterfaces ==null || vpnInterfaces.isEmpty()) {
+ //Clean up the dpn
+ LOG.debug("Cleaning up dpn {} from VPN {}", dpnId, vpnName);
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id);
+ fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
+ }
+ } else {
+ delete(broker, LogicalDatastoreType.OPERATIONAL, id.child(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
+ .vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses.class,
+ new IpAddressesKey(ipAddr)));
+ }
+ }
+ }
+ }
+
+ //TODO: Below Util methods to be removed once VpnUtil methods are exposed in api bundle
+ public static String getVpnRd(DataBroker broker, String vpnName) {
+
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
+ = getVpnInstanceToVpnIdIdentifier(vpnName);
+ Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
+ = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
+
+ String rd = null;
+ if(vpnInstance.isPresent()) {
+ rd = vpnInstance.get().getVrfId();
+ }
+ return rd;
+ }
+
+ static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
+ getVpnInstanceToVpnIdIdentifier(String vpnName) {
+ return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
+ .child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance.class,
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
+ }
+
+
+ static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
+ return InstanceIdentifier.builder(VpnInstanceOpData.class)
+ .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd))
+ .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId)).build();
+ }
+
+ static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String rd) {
+ return InstanceIdentifier.builder(VpnInstanceOpData.class)
+ .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
+ }
+
+ static VpnInstanceOpDataEntry getVpnInstanceOpData(String rd, long vpnId) {
+ return new VpnInstanceOpDataEntryBuilder().setVrfId(rd).setVpnId(vpnId).build();
+ }
+
+ static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.delete(datastoreType, path);
+ tx.submit();
+ }
+
+ static long getVpnId(DataBroker broker, String vpnName) {
+
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
+ = getVpnInstanceToVpnIdIdentifier(vpnName);
+ Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
+ = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
+
+ long vpnId = -1;
+ if(vpnInstance.isPresent()) {
+ vpnId = vpnInstance.get().getVpnId();
+ }
+ return vpnId;
+ }
+
+}
--- /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.fibmanager;
+
+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.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
+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 java.math.BigInteger;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class FibUtil {
+ private static final Logger LOG = LoggerFactory.getLogger(FibUtil.class);
+ 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;
+ }
+
+ static <T extends DataObject> void asyncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.merge(datastoreType, path, data, true);
+ Futures.addCallback(tx.submit(), callback);
+ }
+
+ static <T extends DataObject> void syncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.merge(datastoreType, path, data, true);
+ tx.submit();
+ }
+
+ 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);
+ }
+
+ static InstanceIdentifier<Adjacency> getAdjacencyIdentifier(String vpnInterfaceName, String ipAddress) {
+ return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces.class)
+ .child(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface.class, new org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey(vpnInterfaceName)).augmentation(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyKey(ipAddress)).build();
+ }
+
+ static InstanceIdentifier<Adjacencies> getAdjListPath(String vpnInterfaceName) {
+ return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces.class)
+ .child(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface.class, new org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey(vpnInterfaceName)).augmentation(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies.class).build();
+ }
+
+ static InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(long vpnId, String ipPrefix) {
+ return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.PrefixToInterface.class)
+ .child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.VpnIds.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.VpnIdsKey(vpnId)).child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes.class,
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey(ipPrefix)).build();
+ }
+
+ static InstanceIdentifier<VpnInterface> getVpnInterfaceIdentifier(String vpnInterfaceName) {
+ return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces.class)
+ .child(org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface.class, new org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey(vpnInterfaceName)).build();
+ }
+
+ static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
+ return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpData.class)
+ .child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey(rd))
+ .child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey(dpnId)).build();
+ }
+
+ static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.Extraroute> getVpnToExtrarouteIdentifier(String vrfId, String ipPrefix) {
+ return InstanceIdentifier.builder(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnToExtraroute.class)
+ .child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.Vpn.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.VpnKey(vrfId)).child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.Extraroute.class,
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteKey(ipPrefix)).build();
+ }
+
+ static String getNextHopLabelKey(String rd, String prefix){
+ String key = rd + FibConstants.SEPARATOR + prefix;
+ return key;
+ }
+
+ static void releaseId(IdManagerService idManager, String poolName, String idKey) {
+ ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
+ try {
+ Future<RpcResult<Void>> result = idManager.releaseId(idInput);
+ RpcResult<Void> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when getting Unique Id for key {}", idKey, e);
+ }
+ }
+
+ static final FutureCallback<Void> DEFAULT_CALLBACK =
+ new FutureCallback<Void>() {
+ public void onSuccess(Void result) {
+ LOG.debug("Success in Datastore operation");
+ }
+
+ public void onFailure(Throwable error) {
+ LOG.error("Error in Datastore operation", error);
+ };
+ };
+
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.fibmanager;
+
+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.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.ActionType;
+import org.opendaylight.vpnservice.mdsalutil.BucketInfo;
+import org.opendaylight.vpnservice.mdsalutil.GroupEntity;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
+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.inet.types.rev100924.IpAddressBuilder;
+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.group.types.rev131018.GroupTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetExternalTunnelInterfaceNameOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetInternalOrExternalInterfaceNameInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetInternalOrExternalInterfaceNameOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+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;
+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.idmanager.rev150403.ReleaseIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
+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.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.L3nexthop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.VpnNexthops;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.VpnNexthopsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthopBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthopKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class NexthopManager implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(NexthopManager.class);
+ private final DataBroker broker;
+ private IMdsalApiManager mdsalManager;
+ private OdlInterfaceRpcService interfaceManager;
+ private ItmRpcService itmManager;
+ private IdManagerService idManager;
+ private static final short LPORT_INGRESS_TABLE = 0;
+ private static final short LFIB_TABLE = 20;
+ private static final short FIB_TABLE = 21;
+ private static final short DEFAULT_FLOW_PRIORITY = 10;
+ private static final String NEXTHOP_ID_POOL_NAME = "nextHopPointerPool";
+ private static final long FIXED_DELAY_IN_MILLISECONDS = 4000;
+
+ private static final FutureCallback<Void> DEFAULT_CALLBACK =
+ new FutureCallback<Void>() {
+ public void onSuccess(Void result) {
+ LOG.debug("Success in Datastore write operation");
+ }
+ public void onFailure(Throwable error) {
+ LOG.error("Error in Datastore write operation", error);
+ };
+ };
+
+ /**
+ * Provides nexthop functions
+ * Creates group ID pool
+ *
+ * @param db - dataBroker reference
+ */
+ public NexthopManager(final DataBroker db) {
+ broker = db;
+ }
+
+ @Override
+ public void close() throws Exception {
+ LOG.info("NextHop Manager Closed");
+ }
+
+ public void setInterfaceManager(OdlInterfaceRpcService ifManager) {
+ this.interfaceManager = ifManager;
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ public void setIdManager(IdManagerService idManager) {
+ this.idManager = idManager;
+ createNexthopPointerPool();
+ }
+
+ public void setITMRpcService(ItmRpcService itmManager) {
+ this.itmManager = itmManager;
+ }
+
+ protected void createNexthopPointerPool() {
+ CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
+ .setPoolName(NEXTHOP_ID_POOL_NAME)
+ .setLow(150000L)
+ .setHigh(175000L)
+ .build();
+ //TODO: Error handling
+ Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
+ LOG.trace("NextHopPointerPool result : {}", result);
+ }
+
+ private BigInteger getDpnId(String ofPortId) {
+ String[] fields = ofPortId.split(":");
+ BigInteger dpn = new BigInteger(fields[1]);
+ LOG.debug("DpnId: {}", dpn);
+ return dpn;
+ }
+
+ private String getNextHopKey(long vpnId, String ipAddress){
+ String nhKey = new String("nexthop." + vpnId + ipAddress);
+ return nhKey;
+ }
+
+ private String getNextHopKey(String ifName, String ipAddress){
+ String nhKey = new String("nexthop." + ifName + ipAddress);
+ return nhKey;
+ }
+
+ protected long createNextHopPointer(String nexthopKey) {
+ AllocateIdInput getIdInput = new AllocateIdInputBuilder()
+ .setPoolName(NEXTHOP_ID_POOL_NAME).setIdKey(nexthopKey)
+ .build();
+ //TODO: Proper error handling once IdManager code is complete
+ try {
+ Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
+ RpcResult<AllocateIdOutput> rpcResult = result.get();
+ return rpcResult.getResult().getIdValue();
+ } catch (NullPointerException | InterruptedException | ExecutionException e) {
+ LOG.trace("",e);
+ }
+ return 0;
+ }
+
+ protected void removeNextHopPointer(String nexthopKey) {
+ ReleaseIdInput idInput = new ReleaseIdInputBuilder().
+ setPoolName(NEXTHOP_ID_POOL_NAME)
+ .setIdKey(nexthopKey).build();
+ try {
+ Future<RpcResult<Void>> result = idManager.releaseId(idInput);
+ RpcResult<Void> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when getting Unique Id for key {}", nexthopKey, e);
+ }
+ }
+
+ protected List<ActionInfo> getEgressActionsForInterface(String ifName) {
+ List<ActionInfo> listActionInfo = new ArrayList<ActionInfo>();
+ try {
+ Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
+ interfaceManager.getEgressActionsForInterface(
+ new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName).build());
+ RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.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) {
+ 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) {
+ LOG.warn("Exception when egress actions for interface {}", ifName, e);
+ }
+ return listActionInfo;
+ }
+
+ protected String getTunnelInterfaceName(BigInteger srcDpId, BigInteger dstDpId) {
+ try {
+ Future<RpcResult<GetTunnelInterfaceNameOutput>> result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
+ .setSourceDpid(srcDpId)
+ .setDestinationDpid(dstDpId).build());
+ RpcResult<GetTunnelInterfaceNameOutput> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
+ } else {
+ return rpcResult.getResult().getInterfaceName();
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when getting tunnel interface Id for tunnel between {} and {}", srcDpId, dstDpId, e);
+ }
+
+ return null;
+ }
+
+ protected String getTunnelInterfaceName(BigInteger srcDpId, IpAddress dstIp) {
+ try {
+ Future<RpcResult<GetInternalOrExternalInterfaceNameOutput>> result = itmManager.getInternalOrExternalInterfaceName(new GetInternalOrExternalInterfaceNameInputBuilder()
+ .setSourceDpid(srcDpId)
+ .setDestinationIp(dstIp).build());
+ RpcResult<GetInternalOrExternalInterfaceNameOutput> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to getTunnelInterfaceName returned with Errors {}", rpcResult.getErrors());
+ } else {
+ return rpcResult.getResult().getInterfaceName();
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when getting tunnel interface Id for tunnel between {} and {}", srcDpId, dstIp, e);
+ }
+
+ return null;
+ }
+
+ public long createLocalNextHop(long vpnId, BigInteger dpnId,
+ String ifName, String ipAddress) {
+ long groupId = createNextHopPointer(getNextHopKey(vpnId, ipAddress));
+ String nextHopLockStr = new String(vpnId + ipAddress);
+ synchronized (nextHopLockStr.intern()) {
+ VpnNexthop nexthop = getVpnNexthop(vpnId, ipAddress);
+ LOG.trace("nexthop: {}", nexthop);
+ if (nexthop == null) {
+ Optional<Adjacency> adjacencyData =
+ read(LogicalDatastoreType.OPERATIONAL, getAdjacencyIdentifier(ifName, ipAddress));
+ String macAddress = adjacencyData.isPresent() ? adjacencyData.get().getMacAddress() : null;
+ List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
+ List<ActionInfo> listActionInfo = getEgressActionsForInterface(ifName);
+ BucketInfo bucket = new BucketInfo(listActionInfo);
+ // MAC re-write
+ if (macAddress != null) {
+ listActionInfo.add(0, new ActionInfo(ActionType.set_field_eth_dest, new String[]{macAddress}));
+ //listActionInfo.add(0, new ActionInfo(ActionType.pop_mpls, new String[]{}));
+ } else {
+ //FIXME: Log message here.
+ LOG.debug("mac address for new local nexthop is null");
+ }
+ listBucketInfo.add(bucket);
+ GroupEntity groupEntity = MDSALUtil.buildGroupEntity(
+ dpnId, groupId, ipAddress, GroupTypes.GroupIndirect, listBucketInfo);
+
+ //update MD-SAL DS
+ addVpnNexthopToDS(dpnId, vpnId, ipAddress, groupId);
+
+ // install Group
+ mdsalManager.syncInstallGroup(groupEntity, FIXED_DELAY_IN_MILLISECONDS);
+
+ } else {
+ //nexthop exists already; a new flow is going to point to it, increment the flowrefCount by 1
+ int flowrefCnt = nexthop.getFlowrefCount() + 1;
+ VpnNexthop nh = new VpnNexthopBuilder().setKey(new VpnNexthopKey(ipAddress)).setFlowrefCount(flowrefCnt).build();
+ LOG.trace("Updating vpnnextHop {} for refCount {} to Operational DS", nh, flowrefCnt);
+ syncWrite(LogicalDatastoreType.OPERATIONAL, getVpnNextHopIdentifier(vpnId, ipAddress), nh, DEFAULT_CALLBACK);
+
+ }
+ }
+ return groupId;
+ }
+
+
+ protected void addVpnNexthopToDS(BigInteger dpnId, long vpnId, String ipPrefix, long egressPointer) {
+
+ InstanceIdentifierBuilder<VpnNexthops> idBuilder = InstanceIdentifier.builder(
+ L3nexthop.class)
+ .child(VpnNexthops.class, new VpnNexthopsKey(vpnId));
+
+ // Add nexthop to vpn node
+ VpnNexthop nh = new VpnNexthopBuilder().
+ setKey(new VpnNexthopKey(ipPrefix)).
+ setDpnId(dpnId).
+ setIpAddress(ipPrefix).
+ setFlowrefCount(1).
+ setEgressPointer(egressPointer).build();
+
+ InstanceIdentifier<VpnNexthop> id1 = idBuilder
+ .child(VpnNexthop.class, new VpnNexthopKey(ipPrefix)).build();
+ LOG.trace("Adding vpnnextHop {} to Operational DS", nh);
+ syncWrite(LogicalDatastoreType.OPERATIONAL, id1, nh, DEFAULT_CALLBACK);
+
+ }
+
+
+
+ protected InstanceIdentifier<VpnNexthop> getVpnNextHopIdentifier(long vpnId, String ipAddress) {
+ InstanceIdentifier<VpnNexthop> id = InstanceIdentifier.builder(
+ L3nexthop.class)
+ .child(VpnNexthops.class, new VpnNexthopsKey(vpnId)).child(VpnNexthop.class, new VpnNexthopKey(ipAddress)).build();
+ return id;
+ }
+
+ protected VpnNexthop getVpnNexthop(long vpnId, String ipAddress) {
+
+ // check if vpn node is there
+ InstanceIdentifierBuilder<VpnNexthops> idBuilder =
+ InstanceIdentifier.builder(L3nexthop.class).child(VpnNexthops.class,
+ new VpnNexthopsKey(vpnId));
+ InstanceIdentifier<VpnNexthops> id = idBuilder.build();
+ Optional<VpnNexthops> vpnNexthops = read(LogicalDatastoreType.OPERATIONAL, id);
+ if (vpnNexthops.isPresent()) {
+ // get nexthops list for vpn
+ List<VpnNexthop> nexthops = vpnNexthops.get().getVpnNexthop();
+ for (VpnNexthop nexthop : nexthops) {
+ if (nexthop.getIpAddress().equals(ipAddress)) {
+ // return nexthop
+ LOG.trace("VpnNextHop : {}", nexthop);
+ return nexthop;
+ }
+ }
+ // return null if not found
+ }
+ return null;
+ }
+
+
+ public String getRemoteNextHopPointer(BigInteger localDpnId, BigInteger remoteDpnId,
+ long vpnId, String prefixIp, String nextHopIp) {
+ String tunnelIfName = null;
+ LOG.trace("getRemoteNextHopPointer: input [localDpnId {} remoteDpnId {}, vpnId {}, prefixIp {}, nextHopIp {} ]",
+ localDpnId, remoteDpnId, vpnId, prefixIp, nextHopIp);
+
+ LOG.trace("getRemoteNextHopPointer: Calling ITM with localDpnId {} ", localDpnId);
+ if (nextHopIp != null && !nextHopIp.isEmpty()) {
+ try{
+ // here use the config for tunnel type param
+ tunnelIfName = getTunnelInterfaceName(remoteDpnId, IpAddressBuilder.getDefaultInstance(nextHopIp));
+ }catch(Exception ex){
+ LOG.error("Error while retrieving nexthop pointer for nexthop {} : ", nextHopIp, ex.getMessage());
+ }
+ }
+ return tunnelIfName;
+ }
+
+ public BigInteger getDpnForPrefix(long vpnId, String prefixIp) {
+ VpnNexthop vpnNexthop = getVpnNexthop(vpnId, prefixIp);
+ BigInteger localDpnId = (vpnNexthop == null) ? null : vpnNexthop.getDpnId();
+ return localDpnId;
+ }
+
+
+ private void removeVpnNexthopFromDS(long vpnId, String ipPrefix) {
+
+ InstanceIdentifierBuilder<VpnNexthop> idBuilder = InstanceIdentifier.builder(L3nexthop.class)
+ .child(VpnNexthops.class, new VpnNexthopsKey(vpnId))
+ .child(VpnNexthop.class, new VpnNexthopKey(ipPrefix));
+ InstanceIdentifier<VpnNexthop> id = idBuilder.build();
+ // remove from DS
+ LOG.trace("Removing vpn next hop from datastore : {}", id);
+ delete(LogicalDatastoreType.OPERATIONAL, id);
+ }
+
+
+ public void removeLocalNextHop(BigInteger dpnId, Long vpnId, String ipAddress) {
+
+ String nextHopLockStr = new String(vpnId + ipAddress);
+ synchronized (nextHopLockStr.intern()) {
+ VpnNexthop nh = getVpnNexthop(vpnId, ipAddress);
+ if (nh != null) {
+ int newFlowrefCnt = nh.getFlowrefCount() - 1;
+ if (newFlowrefCnt == 0) { //remove the group only if there are no more flows using this group
+ GroupEntity groupEntity = MDSALUtil.buildGroupEntity(
+ dpnId, nh.getEgressPointer(), ipAddress, GroupTypes.GroupIndirect, null);
+ // remove Group ...
+ mdsalManager.removeGroup(groupEntity);
+ //update MD-SAL DS
+ removeVpnNexthopFromDS(vpnId, ipAddress);
+ //release groupId
+ removeNextHopPointer(getNextHopKey(vpnId, ipAddress));
+ LOG.debug("Local Next hop for {} on dpn {} successfully deleted", ipAddress, dpnId);
+ } else {
+ //just update the flowrefCount of the vpnNexthop
+ VpnNexthop currNh = new VpnNexthopBuilder().setKey(new VpnNexthopKey(ipAddress)).setFlowrefCount(newFlowrefCnt).build();
+ LOG.trace("Updating vpnnextHop {} for refCount {} to Operational DS", currNh, newFlowrefCnt);
+ syncWrite(LogicalDatastoreType.OPERATIONAL, getVpnNextHopIdentifier(vpnId, ipAddress), currNh, DEFAULT_CALLBACK);
+ }
+ } else {
+ //throw error
+ LOG.error("Local Next hop for {} on dpn {} not deleted", ipAddress, dpnId);
+ }
+ }
+
+ }
+
+
+ private <T extends DataObject> Optional<T> read(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;
+ }
+
+ private <T extends DataObject> void asyncWrite(LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.merge(datastoreType, path, data, true);
+ Futures.addCallback(tx.submit(), callback);
+ }
+
+ private <T extends DataObject> void syncWrite(LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.merge(datastoreType, path, data, true);
+ tx.submit();
+ }
+
+ private <T extends DataObject> void delete(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.delete(datastoreType, path);
+ Futures.addCallback(tx.submit(), DEFAULT_CALLBACK);
+ }
+
+ private InstanceIdentifier<Adjacency> getAdjacencyIdentifier(String vpnInterfaceName, String ipAddress) {
+ return InstanceIdentifier.builder(VpnInterfaces.class)
+ .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).augmentation(
+ Adjacencies.class).child(Adjacency.class, new AdjacencyKey(ipAddress)).build();
+ }
+
+ InstanceIdentifier<Adjacencies> getAdjListPath(String vpnInterfaceName) {
+ return InstanceIdentifier.builder(VpnInterfaces.class)
+ .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).augmentation(
+ Adjacencies.class).build();
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.fibmanager.impl.rev150325;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.vpnservice.fibmanager.FibManagerProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+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 FibmanagerImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.fibmanager.impl.rev150325.AbstractFibmanagerImplModule {
+ public FibmanagerImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public FibmanagerImplModule(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.fibmanager.impl.rev150325.FibmanagerImplModule 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() {
+ FibManagerProvider provider = new FibManagerProvider();
+ RpcProviderRegistry rpcProviderRegistry = getRpcregistryDependency();
+ provider.setMdsalManager(getMdsalutilDependency());
+ provider.setVpnmanager(getVpnmanagerDependency());
+ provider.setIdManager(rpcProviderRegistry.getRpcService(IdManagerService.class));
+ provider.setInterfaceManager(rpcProviderRegistry.getRpcService(OdlInterfaceRpcService.class));
+ provider.setITMProvider(rpcProviderRegistry.getRpcService(ItmRpcService.class));
+ getBrokerDependency().registerProvider(provider);
+ return provider;
+ }
+
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: fibmanager-impl yang module local name: fibmanager-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Thu Apr 02 18:16: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.fibmanager.impl.rev150325;
+public class FibmanagerImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.fibmanager.impl.rev150325.AbstractFibmanagerImplModuleFactory {
+
+}
--- /dev/null
+module fibmanager-impl {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:fibmanager:impl";
+ prefix "fibmanager-impl";
+
+ import config { prefix config; revision-date 2013-04-05;}
+ import fibmanager-api { prefix fibmgr-api; revision-date 2015-05-08;}
+ import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
+ import odl-mdsalutil { prefix odl-mdsal; revision-date 2015-04-10;}
+ import vpnmanager-api { prefix odl-vpn; revision-date 2015-05-08;}
+
+ description
+ "Service definition for fibmanager project";
+
+ revision "2015-03-25" {
+ description
+ "Initial revision";
+ }
+
+ identity fibmanager-impl {
+ base config:module-type;
+ config:provided-service fibmgr-api:fibmanager-api;
+ config:java-name-prefix FibmanagerImpl;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case fibmanager-impl {
+ when "/config:modules/config:module/config:type = 'fibmanager-impl'";
+ container broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-broker-osgi-registry;
+ }
+ }
+ }
+ container mdsalutil {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity odl-mdsal:odl-mdsalutil;
+ }
+ }
+ }
+ container vpnmanager {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity odl-vpn:vpnmanager-api;
+ }
+ }
+ }
+ container rpcregistry {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-rpc-registry;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.fibmanager.test;
+
+import java.math.BigInteger;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+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.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnmanager.api.IVpnManager;
+import org.opendaylight.vpnservice.fibmanager.FibManager;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.FibEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntryKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+
+@RunWith(MockitoJUnitRunner.class)
+public class FibManagerTest {
+
+ @Mock
+ DataBroker dataBroker;
+ @Mock
+ ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
+ @Mock
+ ReadOnlyTransaction mockReadTx;
+ @Mock
+ WriteTransaction mockWriteTx;
+ @Mock
+ IMdsalApiManager mdsalManager;
+ @Mock
+ IVpnManager vpnmanager;
+ @Mock
+ VrfTablesKey vrfTableKey;
+
+ MockDataChangedEvent dataChangeEvent;
+ FibManager fibmgr;
+ private static final Long EgressPointer = 11L;
+ VrfEntry vrfEntry;
+ InstanceIdentifier<VrfEntry> identifier;
+ VrfEntryBuilder vrfbuilder;
+ private static final String testRd = "100:1";
+ private static final String prefix = "1.1.2.3";
+ private static final String nexthop = "1.1.1.1";
+ private static final int label = 10;
+ BigInteger Dpn;
+ private static final long vpnId = 101L;
+ private static final long vpnIntfCnt = 2;
+
+ private void SetupMocks() {
+ Dpn = BigInteger.valueOf(100000L);
+ identifier = buildVrfEntryId(testRd, prefix);
+ vrfEntry = buildVrfEntry(testRd, prefix, nexthop, label);
+ fibmgr.setMdsalManager(mdsalManager);
+ fibmgr.setVpnmanager(vpnmanager);
+ when(vrfTableKey.getRouteDistinguisher()).thenReturn(testRd);
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ when(
+ dataBroker.registerDataChangeListener(any(LogicalDatastoreType.class),
+ any(InstanceIdentifier.class), any(DataChangeListener.class),
+ any(DataChangeScope.class))).thenReturn(dataChangeListenerRegistration);
+ dataChangeEvent = new MockDataChangedEvent();
+ vrfbuilder = new VrfEntryBuilder();
+ fibmgr = new FibManager(dataBroker) {
+
+ protected VpnInstanceOpDataEntry getVpnInstance(String rd) {
+ return new VpnInstanceOpDataEntry() {
+
+ @Override
+ public <E extends Augmentation<VpnInstanceOpDataEntry>> E getAugmentation(Class<E> aClass) {
+ return null;
+ }
+
+ @Override
+ public Long getVpnId() {
+ return vpnId;
+ }
+
+ @Override
+ public String getVrfId() {
+ return testRd;
+ }
+
+ @Override
+ public Long getVpnInterfaceCount() { return vpnIntfCnt; }
+
+ @Override
+ public List<VpnToDpnList> getVpnToDpnList() {
+ List <VpnToDpnList> vpnToDpnLists = new ArrayList<>();
+ vpnToDpnLists.add(new VpnToDpnList() {
+ @Override
+ public BigInteger getDpnId() {
+ return Dpn;
+ }
+
+ @Override
+ public List<VpnInterfaces> getVpnInterfaces() {
+ return null;
+ }
+
+ @Override
+ public List<IpAddresses> getIpAddresses() { return null; }
+
+ @Override
+ public VpnToDpnListKey getKey() {
+ return new VpnToDpnListKey(Dpn);
+ }
+
+ @Override
+ public <E extends Augmentation<VpnToDpnList>> E getAugmentation(
+ Class<E> augmentationType) {
+ return null;
+ }
+
+ @Override
+ public Class<? extends DataContainer> getImplementedInterface() {
+ return null;
+ }
+ });
+ return vpnToDpnLists;
+ }
+
+ @Override
+ public VpnInstanceOpDataEntryKey getKey() {
+ return new VpnInstanceOpDataEntryKey(testRd);
+ }
+
+ @Override
+ public List<Long> getRouteEntryId() {
+ return null;
+ }
+
+ @Override
+ public Class<? extends DataContainer> getImplementedInterface() {
+ return null;
+ }
+ };
+ }
+ };
+ SetupMocks();
+ }
+
+ @Test
+ public void testAdd() {
+ dataChangeEvent.created.put(identifier, vrfEntry);
+ //fibmgr.onDataChanged(dataChangeEvent);
+ //Mockito.verify(mdsalManager, Mockito.times(2)).installFlow(any(FlowEntity.class));
+ }
+
+ private VrfEntry buildVrfEntry(String rd, String prefix, String nexthop, int label) {
+ return new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddress(nexthop)
+ .setLabel((long) label).build();
+ }
+
+ public static InstanceIdentifier<VrfTables> buildVrfTableId(String rd) {
+ InstanceIdentifierBuilder<VrfTables> idBuilder =
+ InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
+ InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
+ return vrfTableId;
+ }
+
+ public static InstanceIdentifier<VrfEntry> buildVrfEntryId(String rd, String prefix) {
+ InstanceIdentifierBuilder<VrfEntry> idBuilder =
+ InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd))
+ .child(VrfEntry.class, new VrfEntryKey(prefix));
+ InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
+ return vrfEntryId;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.fibmanager.test;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+class MockDataChangedEvent implements AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> {
+ Map<InstanceIdentifier<?>,DataObject> created = new HashMap<>();
+ Map<InstanceIdentifier<?>,DataObject> updated = new HashMap<>();
+ Map<InstanceIdentifier<?>,DataObject> original = new HashMap<>();
+ Set<InstanceIdentifier<?>> removed = new HashSet<>();
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
+ return created;
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getUpdatedData() {
+ return updated;
+ }
+
+ @Override
+ public Set<InstanceIdentifier<?>> getRemovedPaths() {
+ return removed;
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getOriginalData() {
+ return original;
+ }
+
+ @Override
+ public DataObject getOriginalSubtree() {
+ throw new UnsupportedOperationException("Not implemented by mock");
+ }
+
+ @Override
+ public DataObject getUpdatedSubtree() {
+ throw new UnsupportedOperationException("Not implemented by mock");
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: --><!--
+Copyright (c) 2015 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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>fibmanager-shell</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>fibmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.console</artifactId>
+ <version>${karaf.shell.console.version}</version>
+ </dependency>
+ </dependencies>
+
+</project>
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.vpnservice.fibmanager.shell;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.fibmanager.api.IFibManager;
+
+@Command(scope = "vpnservice", name = "fib-show", description = "Displays fib entries")
+public class ShowFibCommand extends OsgiCommandSupport {
+ private IFibManager fibManager;
+
+ public void setFibManager(IFibManager fibManager) {
+ this.fibManager = fibManager;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ for (String p : fibManager.printFibEntries()) {
+ System.out.println(p);
+ }
+ return null;
+ }
+}
--- /dev/null
+<!-- * Copyright (c) 2015 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
+-->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <reference id="fibManagerRef" interface="org.opendaylight.fibmanager.api.IFibManager" availability="optional"/>
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+
+ <command>
+ <action class="org.opendaylight.vpnservice.fibmanager.shell.ShowFibCommand">
+ <property name="fibManager" ref="fibManagerRef"/>
+ </action>
+ </command>
+
+ </command-bundle>
+
+</blueprint>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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,
+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.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>fibmanager-aggregator</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <name>fibmanager</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>fibmanager-api</module>
+ <module>fibmanager-impl</module>
+ <module>fibmanager-shell</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>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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>binding-parent</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/binding-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>idmanager-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.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+module id-manager {
+ namespace "urn:opendaylight:vpnservice:idmanager";
+ prefix idmgr;
+
+ revision "2015-04-03" {
+ description "YANG model describes methods for allocating or releasing Ids as well as to create/delete Id Pools. The child pools
+ are created inside the IdManager. This helps to improve ID Pool scalability/performance";
+ }
+
+ container id-pools {
+ description "Parent Id Pool is responsible allocating block (or) set of Ids to child Id Pools. The number of child pools are determined using some algorthimic approach inside IdManager. For example, spawning child pools based on Id allocation request rate for the given Pool, one child pool per blade in the cluster etc";
+ config true;
+ list id-pool {
+ key "pool-name";
+ leaf pool-name {
+ type string;
+ mandatory true;
+ }
+ leaf block-size {
+ type uint16;
+ mandatory true;
+ }
+ leaf parent-pool-name {
+ type string;
+ }
+ list child-pools {
+ key "child-pool-name";
+ leaf child-pool-name {
+ type string;
+ mandatory true;
+ }
+ leaf last-access-time {
+ type uint32;
+ }
+ }
+ list id-entries {
+ description "Id entry for the given Id Pool, where id-key is used to identify the id entry";
+ key "id-key";
+ leaf id-key { type string;}
+ leaf id-value { type uint32;}
+ }
+ container available-ids-holder {
+ uses available-ids;
+ }
+ container released-ids-holder {
+ uses released-ids;
+ }
+ }
+ }
+
+ grouping available-ids {
+ leaf start {
+ type uint32;
+ }
+ leaf end {
+ type uint32;
+ }
+ leaf cursor {
+ type int64;
+ }
+ }
+
+ grouping released-ids {
+ leaf available-id-count {
+ type uint32;
+ }
+ leaf delayed-time-sec {
+ type uint32;
+ mandatory true;
+ }
+ list delayed-id-entries {
+ uses delayed-id-entry;
+ }
+ }
+
+ grouping delayed-id-entry {
+ leaf id {
+ type uint32;
+ mandatory true;
+ }
+ leaf ready-time-sec {
+ type uint32;
+ mandatory true;
+ }
+ }
+
+ rpc createIdPool {
+ input {
+ leaf pool-name {
+ type string;
+ }
+ leaf low {
+ type uint32;
+ }
+ leaf high {
+ type uint32;
+ }
+ }
+ }
+
+ rpc deleteIdPool {
+ input {
+ leaf pool-name {
+ type string;
+ }
+ }
+ }
+
+ rpc allocateId {
+ input {
+ leaf pool-name {
+ type string;
+ }
+ leaf id-key {
+ type string;
+ }
+ }
+ output {
+ leaf id-value {
+ type uint32;
+ }
+ }
+ }
+
+ rpc releaseId {
+ input {
+ leaf pool-name {
+ type string;
+ }
+ leaf id-key {
+ type string;
+ }
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: --><!--
+Copyright (c) 2015 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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>idmanager-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>idmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>lockmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>mdsalutil-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ </dependencies>
+
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright (c) 2015 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:idmanager:impl?module=idmanager-impl&revision=2015-03-25</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</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:idmanager:impl">prefix:idmanager-impl</type>
+ <name>idmanager-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>
+ <rpc-registry>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+ <name>binding-rpc-broker</name>
+ </rpc-registry>
+ </module>
+ </modules>
+ </data>
+ </configuration>
+</snapshot>
--- /dev/null
+/*
+ * Copyright (c) 2015 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.idmanager;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.concurrent.Future;
+
+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.mdsalutil.MDSALUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.DeleteIdPoolInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
+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.IdPoolBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolderBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPools;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolderBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+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 com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+
+public class IdManager implements IdManagerService, AutoCloseable{
+ private static final Logger LOG = LoggerFactory.getLogger(IdManager.class);
+
+ private static final long DEFAULT_IDLE_TIME = 24 * 60 * 60;
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private LockManagerService lockManager;
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("IDManager Closed");
+ }
+
+ public IdManager(final DataBroker db) {
+ broker = db;
+ }
+
+ public void setLockManager(LockManagerService lockManager) {
+ this.lockManager = lockManager;
+ }
+
+ @Override
+ public Future<RpcResult<Void>> createIdPool(CreateIdPoolInput input) {
+ LOG.debug("createIdPool called with input {}", input);
+ String poolName = input.getPoolName();
+ long low = input.getLow();
+ long high = input.getHigh();
+ long blockSize = IdUtils.computeBlockSize(low, high);
+ RpcResultBuilder<Void> createIdPoolRpcBuilder;
+ IdUtils.lockPool(lockManager, poolName);
+ try {
+ InstanceIdentifier<IdPool> idPoolInstanceIdentifier = IdUtils.getIdPoolInstance(poolName);
+ poolName = poolName.intern();
+ IdPool idPool;
+ idPool = createGlobalPool(poolName, low, high, blockSize, idPoolInstanceIdentifier);
+ String localPoolName = IdUtils.getLocalPoolName(poolName);
+ if (createLocalPool(localPoolName, idPool)) {
+ LOG.debug("Updating global id pool {} with childPool {}", poolName, localPoolName);
+ updateChildPool(poolName, localPoolName);
+ }
+ createIdPoolRpcBuilder = RpcResultBuilder.success();
+ } catch (Exception ex) {
+ LOG.error("Creation of Id Pool {} failed due to {}", poolName, ex);
+ createIdPoolRpcBuilder = RpcResultBuilder.failed();
+ createIdPoolRpcBuilder.withError(ErrorType.APPLICATION, ex.getMessage());
+ } finally {
+ IdUtils.unlockPool(lockManager, poolName);
+ }
+ return Futures.immediateFuture(createIdPoolRpcBuilder.build());
+ }
+
+ @Override
+ public Future<RpcResult<AllocateIdOutput>> allocateId(AllocateIdInput input) {
+ LOG.debug("AllocateId called with input {}", input);
+ String idKey = input.getIdKey();
+ String poolName = input.getPoolName();
+ String localPoolName = IdUtils.getLocalPoolName(poolName);
+ RpcResultBuilder<AllocateIdOutput> allocateIdRpcBuilder;
+ long newIdValue = -1;
+ AllocateIdOutputBuilder output = new AllocateIdOutputBuilder();
+ try {
+ newIdValue = allocateIdFromLocalPool(poolName, localPoolName, idKey);
+ output.setIdValue(newIdValue);
+ allocateIdRpcBuilder = RpcResultBuilder.success();
+ allocateIdRpcBuilder.withResult(output.build());
+ } catch (Exception ex) {
+ LOG.error("Allocate id in pool {} failed due to {}", poolName, ex);
+ allocateIdRpcBuilder = RpcResultBuilder.failed();
+ allocateIdRpcBuilder.withError(ErrorType.APPLICATION, ex.getMessage());
+ }
+ return Futures.immediateFuture(allocateIdRpcBuilder.build());
+ }
+
+ @Override
+ public Future<RpcResult<Void>> deleteIdPool(DeleteIdPoolInput input) {
+ LOG.debug("DeleteIdPool called with input {}", input);
+ String poolName = input.getPoolName();
+ RpcResultBuilder<Void> deleteIdPoolRpcBuilder;
+ try {
+ InstanceIdentifier<IdPool> idPoolToBeDeleted = IdUtils.getIdPoolInstance(poolName);
+ poolName = poolName.intern();
+ synchronized(poolName) {
+ IdPool idPool = getIdPool(idPoolToBeDeleted);
+ List<ChildPools> childPoolList = idPool.getChildPools();
+ if (childPoolList != null) {
+ for (ChildPools childPoolName : childPoolList) {
+ deletePool(childPoolName.getChildPoolName());
+ }
+ }
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, idPoolToBeDeleted);
+ LOG.debug("Deleted id pool {}", poolName);
+ }
+ deleteIdPoolRpcBuilder = RpcResultBuilder.success();
+ }
+ catch (Exception ex) {
+ LOG.error("Delete id in pool {} failed due to {}", poolName, ex);
+ deleteIdPoolRpcBuilder = RpcResultBuilder.failed();
+ deleteIdPoolRpcBuilder.withError(ErrorType.APPLICATION, ex.getMessage());
+ }
+ return Futures.immediateFuture(deleteIdPoolRpcBuilder.build());
+ }
+
+ @Override
+ public Future<RpcResult<Void>> releaseId(ReleaseIdInput input) {
+ String poolName = input.getPoolName();
+ String idKey = input.getIdKey();
+ RpcResultBuilder<Void> releaseIdRpcBuilder;
+ try {
+ releaseIdFromLocalPool(IdUtils.getLocalPoolName(poolName), idKey);
+ releaseIdRpcBuilder = RpcResultBuilder.success();
+ } catch (Exception ex) {
+ LOG.error("Release id {} from pool {} failed due to {}", idKey, poolName, ex);
+ releaseIdRpcBuilder = RpcResultBuilder.failed();
+ releaseIdRpcBuilder.withError(ErrorType.APPLICATION, ex.getMessage());
+ }
+ return Futures.immediateFuture(releaseIdRpcBuilder.build());
+ }
+
+ private long allocateIdFromLocalPool(String parentPoolName, String localPoolName, String idKey) {
+ LOG.trace("Allocating id from local pool {}. Parent pool {}. Idkey {}", localPoolName, parentPoolName, idKey);
+ long newIdValue = -1;
+ InstanceIdentifier<IdPool> localIdPoolInstanceIdentifier = IdUtils.getIdPoolInstance(localPoolName);
+ localPoolName = localPoolName.intern();
+ synchronized (localPoolName) {
+ InstanceIdentifier<IdPool> parentIdPoolInstanceIdentifier = IdUtils.getIdPoolInstance(parentPoolName);
+ IdPool parentIdPool = getIdPool(parentIdPoolInstanceIdentifier);
+ IdPool localPool = null;
+ try {
+ localPool = getIdPool(localIdPoolInstanceIdentifier);
+ } catch (NoSuchElementException e){
+ LOG.trace("Creating local pool {} since it was not present", localPoolName);
+ localPool = IdUtils.createLocalIdPool(localPoolName, parentIdPool);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, localIdPoolInstanceIdentifier, localPool);
+ IdUtils.lockPool(lockManager, parentPoolName);
+ try {
+ updateChildPool(parentPoolName, localPoolName);
+ } finally {
+ IdUtils.unlockPool(lockManager, parentPoolName);
+ }
+ LOG.debug("Updating global id pool {} with childPool {}", parentPoolName, localPoolName);
+ }
+ IdEntries newIdEntry;
+ List<IdEntries> idEntries = parentIdPool.getIdEntries();
+ AvailableIdsHolderBuilder availableIds = IdUtils.getAvailableIdsHolderBuilder(localPool);
+ ReleasedIdsHolderBuilder releasedIds = IdUtils.getReleaseIdsHolderBuilder(localPool);
+ //Calling cleanupExcessIds since there could be excessive ids.
+ cleanupExcessIds(availableIds, releasedIds, parentPoolName, localPool.getBlockSize());
+ if (idEntries == null) {
+ idEntries = new LinkedList<IdEntries>();
+ } else {
+ InstanceIdentifier<IdEntries> existingId = IdUtils.getIdEntry(parentIdPoolInstanceIdentifier, idKey);
+ Optional<IdEntries> existingIdEntry = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, existingId);
+ if (existingIdEntry.isPresent()) {
+ newIdValue = existingIdEntry.get().getIdValue();
+ LOG.debug("Existing id {} for the key {} ", idKey, newIdValue);
+ InstanceIdentifier<ReleasedIdsHolder> releasedIdsHolderInstanceIdentifier = InstanceIdentifier
+ .builder(IdPools.class).child(IdPool.class, new IdPoolKey(localPoolName)).child(ReleasedIdsHolder.class).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, releasedIdsHolderInstanceIdentifier, releasedIds.build());
+ return newIdValue;
+ }
+ }
+ newIdValue = getIdFromPool(localPool, availableIds, releasedIds);
+ LOG.debug("The newIdValue {} for the idKey {}", newIdValue, idKey);
+ newIdEntry = IdUtils.createIdEntries(idKey, newIdValue);
+ idEntries.add(newIdEntry);
+ LOG.debug("The availablelIds are {}", availableIds.build());
+ localPool = new IdPoolBuilder(localPool).setAvailableIdsHolder(availableIds.build())
+ .setReleasedIdsHolder(releasedIds.build()).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, localIdPoolInstanceIdentifier, localPool);
+ updateChildPool(localPool.getParentPoolName(), localPoolName);
+ //Updating id entries in the parent pool. This will be used for restart scenario
+ IdUtils.lockPool(lockManager, parentPoolName);
+ try {
+ parentIdPool = getIdPool(parentIdPoolInstanceIdentifier);
+ IdPool parentPool = new IdPoolBuilder(parentIdPool).setIdEntries(idEntries).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, parentIdPoolInstanceIdentifier, parentPool);
+ } catch (Exception ex) {
+ LOG.error("Saving of Id entries to parent pool {} failed due to {}", parentPoolName, ex);
+ } finally {
+ IdUtils.unlockPool(lockManager, parentPoolName);
+ }
+ }
+ return newIdValue;
+ }
+
+ private long getIdFromPool(IdPool pool, AvailableIdsHolderBuilder availableIds, ReleasedIdsHolderBuilder releasedIds) {
+ long newIdValue = -1;
+ while (true) {
+ newIdValue = IdUtils.getIdFromReleaseIdsIfAvailable(releasedIds);
+ if (newIdValue != -1) {
+ LOG.debug("Retrieved id value {} from released id holder", newIdValue);
+ return newIdValue;
+ }
+ newIdValue = IdUtils.getIdFromAvailableIds(availableIds);
+ if (newIdValue != -1) {
+ LOG.debug("Creating a new id {} for the pool: {} ", newIdValue, pool.getPoolName());
+ return newIdValue;
+ }
+ long idCount = allocateIdBlockFromParentPool(pool.getParentPoolName(), availableIds, releasedIds);
+ if (idCount <= 0) {
+ LOG.debug("Unable to allocate Id block from global pool");
+ throw new RuntimeException(String.format("Ids exhausted for pool : %s", pool.getPoolName()));
+ }
+ }
+ }
+
+ /**
+ * Changes made to releaseIds and AvailableIds are not persisted.
+ * @param availableIds
+ * @param releasedIds
+ * @param parentPoolName
+ * @param blockSize
+ */
+ private void cleanupExcessIds(AvailableIdsHolderBuilder availableIds, ReleasedIdsHolderBuilder releasedIds, String parentPoolName, int blockSize) {
+ IdUtils.processDelayList(releasedIds);
+ long totalAvailableIdCount = releasedIds.getAvailableIdCount() + IdUtils.getAvailableIdsCount(availableIds);
+ if (totalAvailableIdCount > blockSize * 2) {
+ parentPoolName = parentPoolName.intern();
+ InstanceIdentifier<ReleasedIdsHolder> releasedIdInstanceIdentifier = IdUtils.getReleasedIdsHolderInstance(parentPoolName);
+ IdUtils.lockPool(lockManager, parentPoolName);
+ try {
+ Optional<ReleasedIdsHolder> releasedIdsHolder = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, releasedIdInstanceIdentifier);
+ ReleasedIdsHolderBuilder releasedIdsParent;
+ if (!releasedIdsHolder.isPresent()) {
+ LOG.error("ReleasedIds not present in parent pool. Unable to cleanup excess ids");
+ return;
+ }
+ releasedIdsParent = new ReleasedIdsHolderBuilder(releasedIdsHolder.get());
+ LOG.debug("Releasing excesss Ids from local pool");
+ IdUtils.freeExcessAvailableIds(releasedIds, releasedIdsParent, blockSize);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, releasedIdInstanceIdentifier, releasedIdsParent.build());
+ } finally {
+ IdUtils.unlockPool(lockManager, parentPoolName);
+ }
+ }
+ }
+
+ /**
+ * Changes made to availableIds and releasedIds will not be persisted to the datastore
+ * @param parentPoolName
+ * @param availableIdsBuilder
+ * @param releasedIdsBuilder
+ * @return
+ */
+ private long allocateIdBlockFromParentPool(String parentPoolName,
+ AvailableIdsHolderBuilder availableIdsBuilder, ReleasedIdsHolderBuilder releasedIdsBuilder) {
+ LOG.debug("Allocating block of id from parent pool {}", parentPoolName);
+ InstanceIdentifier<IdPool> idPoolInstanceIdentifier = IdUtils.getIdPoolInstance(parentPoolName);
+ parentPoolName = parentPoolName.intern();
+ long idCount = -1;
+ IdUtils.lockPool(lockManager, parentPoolName);
+ try {
+ IdPool parentIdPool = getIdPool(idPoolInstanceIdentifier);
+ ReleasedIdsHolderBuilder releasedIdsBuilderParent = IdUtils.getReleaseIdsHolderBuilder(parentIdPool);
+ while (true) {
+ idCount = allocateIdBlockFromReleasedIdsHolder(releasedIdsBuilder, releasedIdsBuilderParent, parentIdPool);
+ if (idCount > 0) {
+ return idCount;
+ }
+ idCount = allocateIdBlockFromAvailableIdsHolder(availableIdsBuilder, parentIdPool);
+ if (idCount > 0) {
+ return idCount;
+ }
+ idCount = getIdsFromOtherChildPools(releasedIdsBuilderParent, parentIdPool);
+ if (idCount <= 0) {
+ LOG.debug("Unable to allocate Id block from global pool");
+ throw new RuntimeException(String.format("Ids exhausted for pool : %s", parentPoolName));
+ }
+ }
+ }
+ finally {
+ IdUtils.unlockPool(lockManager, parentPoolName);
+ }
+ }
+
+ private long getIdsFromOtherChildPools(ReleasedIdsHolderBuilder releasedIdsBuilderParent, IdPool parentIdPool) {
+ List<ChildPools> childPoolsList = parentIdPool.getChildPools();
+ // Sorting the child pools on last accessed time so that the pool that was not accessed for a long time comes first.
+ Collections.sort(childPoolsList, new Comparator<ChildPools>() {
+ @Override
+ public int compare(ChildPools childPool1, ChildPools childPool2) {
+ return childPool1.getLastAccessTime().compareTo(childPool2.getLastAccessTime());
+ }
+ });
+ long currentTime = System.currentTimeMillis() / 1000;
+ for (ChildPools childPools : childPoolsList) {
+ if (childPools.getLastAccessTime() + DEFAULT_IDLE_TIME < currentTime) {
+ break;
+ }
+ if (!childPools.getChildPoolName().equals(IdUtils.getLocalPoolName(parentIdPool.getPoolName()))) {
+ InstanceIdentifier<IdPool> idPoolInstanceIdentifier = IdUtils.getIdPoolInstance(childPools.getChildPoolName());
+ IdPool otherChildPool = getIdPool(idPoolInstanceIdentifier);
+ ReleasedIdsHolderBuilder releasedIds = IdUtils.getReleaseIdsHolderBuilder(otherChildPool);
+ AvailableIdsHolderBuilder availableIds = IdUtils.getAvailableIdsHolderBuilder(otherChildPool);
+ long totalAvailableIdCount = releasedIds.getDelayedIdEntries().size() + IdUtils.getAvailableIdsCount(availableIds);
+ List<DelayedIdEntries> delayedIdEntriesChild = releasedIds.getDelayedIdEntries();
+ List<DelayedIdEntries> delayedIdEntriesParent = releasedIdsBuilderParent.getDelayedIdEntries();
+ if (delayedIdEntriesParent == null) {
+ delayedIdEntriesParent = new LinkedList<>();
+ }
+ delayedIdEntriesParent.addAll(delayedIdEntriesChild);
+ delayedIdEntriesChild.removeAll(delayedIdEntriesChild);
+ while (IdUtils.isIdAvailable(availableIds)) {
+ long cursor = availableIds.getCursor() + 1;
+ delayedIdEntriesParent.add(new DelayedIdEntriesBuilder().setId(cursor).setReadyTimeSec(System.currentTimeMillis()).build());
+ availableIds.setCursor(cursor);
+ }
+ long count = releasedIdsBuilderParent.getAvailableIdCount() + totalAvailableIdCount;
+ releasedIdsBuilderParent.setDelayedIdEntries(delayedIdEntriesParent).setAvailableIdCount(count);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier,
+ new IdPoolBuilder(otherChildPool).setAvailableIdsHolder(availableIds.build()).setReleasedIdsHolder(releasedIds.build()).build());
+ return totalAvailableIdCount;
+ }
+ }
+ return 0;
+ }
+
+ private long allocateIdBlockFromReleasedIdsHolder(ReleasedIdsHolderBuilder releasedIdsBuilderChild, ReleasedIdsHolderBuilder releasedIdsBuilderParent, IdPool parentIdPool) {
+ if (releasedIdsBuilderParent.getAvailableIdCount() == 0) {
+ LOG.debug("Ids unavailable in releasedIds of parent pool {}", parentIdPool);
+ return 0;
+ }
+ List<DelayedIdEntries> delayedIdEntriesParent = releasedIdsBuilderParent.getDelayedIdEntries();
+ List<DelayedIdEntries> delayedIdEntriesChild = releasedIdsBuilderChild.getDelayedIdEntries();
+ if (delayedIdEntriesChild == null) {
+ delayedIdEntriesChild = new LinkedList<DelayedIdEntries>();
+ }
+ int idCount = Math.min(delayedIdEntriesParent.size(), parentIdPool.getBlockSize());
+ List<DelayedIdEntries> idEntriesToBeRemoved = delayedIdEntriesParent.subList(0, idCount);
+ delayedIdEntriesChild.addAll(0, idEntriesToBeRemoved);
+ delayedIdEntriesParent.removeAll(idEntriesToBeRemoved);
+ releasedIdsBuilderParent.setDelayedIdEntries(delayedIdEntriesParent);
+ releasedIdsBuilderChild.setDelayedIdEntries(delayedIdEntriesChild);
+ releasedIdsBuilderChild.setAvailableIdCount(releasedIdsBuilderChild.getAvailableIdCount() + idCount);
+ InstanceIdentifier<ReleasedIdsHolder> releasedIdsHolderInstanceIdentifier = InstanceIdentifier
+ .builder(IdPools.class).child(IdPool.class,
+ new IdPoolKey(parentIdPool.getPoolName())).child(ReleasedIdsHolder.class).build();
+ releasedIdsBuilderParent.setAvailableIdCount(releasedIdsBuilderParent.getAvailableIdCount() - idCount);
+ LOG.debug("Allocated {} ids from releasedIds of parent pool {}", idCount, parentIdPool);
+ MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, releasedIdsHolderInstanceIdentifier, releasedIdsBuilderParent.build());
+ return idCount;
+ }
+
+ private long allocateIdBlockFromAvailableIdsHolder(AvailableIdsHolderBuilder availableIdsBuilder, IdPool parentIdPool) {
+ long idCount = 0;
+ AvailableIdsHolderBuilder availableIdsBuilderParent = IdUtils.getAvailableIdsHolderBuilder(parentIdPool);
+ long end = availableIdsBuilderParent.getEnd();
+ long cur = availableIdsBuilderParent.getCursor();
+ if (!IdUtils.isIdAvailable(availableIdsBuilderParent)) {
+ LOG.debug("Ids exhausted in parent pool {}", parentIdPool);
+ return idCount;
+ }
+ // Update availableIdsHolder of Local Pool
+ availableIdsBuilder.setStart(cur + 1);
+ idCount = Math.min(end - cur, parentIdPool.getBlockSize());
+ availableIdsBuilder.setEnd(cur + idCount);
+ availableIdsBuilder.setCursor(cur);
+ // Update availableIdsHolder of Global Pool
+ InstanceIdentifier<AvailableIdsHolder> availableIdsHolderInstanceIdentifier = InstanceIdentifier
+ .builder(IdPools.class).child(IdPool.class,
+ new IdPoolKey(parentIdPool.getPoolName())).child(AvailableIdsHolder.class).build();
+ availableIdsBuilderParent.setCursor(cur + idCount);
+ LOG.debug("Allocated {} ids from availableIds of global pool {}", idCount, parentIdPool);
+ MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, availableIdsHolderInstanceIdentifier, availableIdsBuilderParent.build());
+ return idCount;
+ }
+
+ private void releaseIdFromLocalPool(String poolName, String idKey) {
+ InstanceIdentifier<IdPool> localIdPoolInstanceIdentifier = IdUtils.getIdPoolInstance(poolName);
+ poolName = poolName.intern();
+ synchronized (poolName) {
+ IdPool localPool = getIdPool(localIdPoolInstanceIdentifier);
+ String parentPoolName = localPool.getParentPoolName();
+ InstanceIdentifier<IdPool> parentIdPoolInstanceIdentifier = IdUtils.getIdPoolInstance(parentPoolName);
+ IdPool parentIdPool = getIdPool(parentIdPoolInstanceIdentifier);
+ List<IdEntries> idEntries = parentIdPool.getIdEntries();
+ List<IdEntries> newIdEntries = idEntries;
+ if (idEntries == null) {
+ throw new RuntimeException("Id Entries does not exist");
+ }
+ InstanceIdentifier<IdEntries> existingId = IdUtils.getIdEntry(parentIdPoolInstanceIdentifier, idKey);
+ Optional<IdEntries> existingIdEntryObject = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, existingId);
+ if (!existingIdEntryObject.isPresent()) {
+ throw new RuntimeException(String.format("Specified Id key %s does not exist in id pool %s", idKey, poolName));
+ }
+ IdEntries existingIdEntry = existingIdEntryObject.get();
+ long idValue = existingIdEntry.getIdValue();
+ boolean isRemoved = newIdEntries.remove(existingIdEntry);
+ LOG.debug("The entry {} is removed {}", existingIdEntry, isRemoved);
+ ReleasedIdsHolderBuilder releasedIds = IdUtils.getReleaseIdsHolderBuilder(localPool);
+ AvailableIdsHolderBuilder availableIds = IdUtils.getAvailableIdsHolderBuilder(localPool);
+ long delayTime = System.currentTimeMillis() / 1000 + releasedIds.getDelayedTimeSec();
+ DelayedIdEntries delayedIdEntry = IdUtils.createDelayedIdEntry(idValue, delayTime);
+ List<DelayedIdEntries> delayedIdEntries = releasedIds.getDelayedIdEntries();
+ if (delayedIdEntries == null) {
+ delayedIdEntries = new LinkedList<DelayedIdEntries>();
+ }
+ delayedIdEntries.add(delayedIdEntry);
+ long availableIdCount = releasedIds
+ .getAvailableIdCount() == null ? 0
+ : releasedIds.getAvailableIdCount();
+ releasedIds.setDelayedIdEntries(delayedIdEntries);
+ releasedIds.setAvailableIdCount(availableIdCount);
+ //Calling cleanupExcessIds since there could be excessive ids.
+ cleanupExcessIds(availableIds, releasedIds, parentPoolName, localPool.getBlockSize());
+ localPool = new IdPoolBuilder(localPool)
+ .setAvailableIdsHolder(availableIds.build())
+ .setReleasedIdsHolder(releasedIds.build()).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, localIdPoolInstanceIdentifier, localPool);
+ LOG.debug("Released id ({}, {}) from pool {}", idKey, idValue, poolName);
+ //Updating id entries in the parent pool. This will be used for restart scenario
+ IdUtils.lockPool(lockManager, parentPoolName);
+ try {
+ parentIdPool = getIdPool(parentIdPoolInstanceIdentifier);
+ IdPool parentPool = new IdPoolBuilder(parentIdPool).setIdEntries(newIdEntries).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, parentIdPoolInstanceIdentifier, parentPool);
+ } catch (Exception ex) {
+ LOG.error("Saving of Id entries to parent pool {} failed due to {}", parentPoolName, ex);
+ } finally {
+ IdUtils.unlockPool(lockManager, parentPoolName);
+ }
+ }
+ }
+
+ private IdPool createGlobalPool(String poolName, long low, long high,
+ long blockSize, InstanceIdentifier<IdPool> idPoolInstanceIdentifier) {
+ IdPool idPool;
+ Optional<IdPool> existingIdPool = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier);
+ if (!existingIdPool.isPresent()) {
+ LOG.debug("Creating new global pool {}", poolName);
+ idPool = IdUtils.createGlobalPool(poolName, low, high, blockSize);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier, idPool);
+ }
+ else {
+ idPool = existingIdPool.get();
+ LOG.debug("GlobalPool exists {}", idPool);
+ }
+ return idPool;
+ }
+
+ private boolean createLocalPool(String localPoolName, IdPool idPool) {
+ localPoolName = localPoolName.intern();
+ synchronized (localPoolName) {
+ InstanceIdentifier<IdPool> localIdPoolInstanceIdentifier = IdUtils.getIdPoolInstance(localPoolName);
+ Optional<IdPool> localIdPool = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, localIdPoolInstanceIdentifier);
+ if (!localIdPool.isPresent()) {
+ LOG.debug("Creating new local pool");
+ IdPool newLocalIdPool = IdUtils.createLocalIdPool(localPoolName, idPool);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, localIdPoolInstanceIdentifier, newLocalIdPool);
+ LOG.debug("Local pool created {}", newLocalIdPool);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void deletePool(String poolName) {
+ InstanceIdentifier<IdPool> idPoolToBeDeleted = IdUtils.getIdPoolInstance(poolName);
+ synchronized (poolName) {
+ Optional<IdPool> idPool = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, idPoolToBeDeleted);
+ if (idPool.isPresent()) {
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, idPoolToBeDeleted);
+ LOG.debug("Deleted local pool {}", poolName);
+ }
+ }
+ }
+
+ private IdPool getIdPool(InstanceIdentifier<IdPool> idPoolInstanceIdentifier) {
+ Optional<IdPool> idPool = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier);
+ if (!idPool.isPresent()) {
+ throw new NoSuchElementException(String.format("Specified pool %s does not exist" , idPool));
+ }
+ LOG.trace("GetIdPool : Read id pool {} ", idPool);
+ return idPool.get();
+ }
+
+ private void updateChildPool(String poolName, String localPoolName) {
+ ChildPools childPool = IdUtils.createChildPool(localPoolName);
+ InstanceIdentifier<ChildPools> childPoolInstanceIdentifier = IdUtils.getChildPoolsInstanceIdentifier(poolName, localPoolName);
+ MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, childPoolInstanceIdentifier, childPool);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.idmanager;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+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.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class IdManagerServiceProvider implements BindingAwareProvider,
+ AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(IdManagerServiceProvider.class);
+ private IdManager idManager;
+ private RpcProviderRegistry rpcProviderRegistry;
+ private LockManagerService lockManager;
+
+ public RpcProviderRegistry getRpcProviderRegistry() {
+ return rpcProviderRegistry;
+ }
+
+ public void setRpcProviderRegistry(RpcProviderRegistry rpcProviderRegistry) {
+ this.rpcProviderRegistry = rpcProviderRegistry;
+ }
+
+ public void setLockManager(LockManagerService lockManager) {
+ this.lockManager = lockManager;
+ }
+
+ @Override
+ public void onSessionInitiated(ProviderContext session){
+ LOG.info("IDManagerserviceProvider Session Initiated");
+ try {
+ final DataBroker dataBroker = session.getSALService(DataBroker.class);
+ idManager = new IdManager(dataBroker);
+ idManager.setLockManager(lockManager);
+ final BindingAwareBroker.RpcRegistration<IdManagerService> rpcRegistration = getRpcProviderRegistry().addRpcImplementation(IdManagerService.class, idManager);
+ } catch (Exception e) {
+ LOG.error("Error initializing services", e);
+ }
+ }
+
+ public IdManagerServiceProvider(RpcProviderRegistry rpcRegistry) {
+ this.rpcProviderRegistry = rpcRegistry;
+ }
+
+ @Override
+ public void close() throws Exception {
+ idManager.close();
+ }
+ }
+
+
+
+
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.idmanager;
+
+import java.net.InetAddress;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.DelayedIdEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools;
+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.IdPoolBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolderBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPools;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPoolsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPoolsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntriesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolderBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.UnlockInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.UnlockInputBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.net.InetAddresses;
+
+class IdUtils {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(IdUtils.class);
+ private static final long DEFAULT_DELAY_TIME = 30;
+ private static final long DEFAULT_AVAILABLE_ID_COUNT = 0;
+ private static final int DEFAULT_BLOCK_SIZE_DIFF = 50;
+
+ private static int BLADE_ID;
+ static {
+ try {
+ BLADE_ID = InetAddresses.coerceToInteger(InetAddress.getLocalHost());
+ } catch (Exception e) {
+ LOGGER.error("IdManager - Exception - {}", e.getMessage());
+ }
+ }
+
+ protected static InstanceIdentifier<IdEntries> getIdEntry(InstanceIdentifier<IdPool> poolName, String idKey) {
+ InstanceIdentifier.InstanceIdentifierBuilder<IdEntries> idEntriesBuilder = poolName
+ .builder().child(IdEntries.class, new IdEntriesKey(idKey));
+ InstanceIdentifier<IdEntries> idEntry = idEntriesBuilder.build();
+ return idEntry;
+ }
+
+ protected static IdEntries createIdEntries(String idKey, long newIdVal) {
+ return new IdEntriesBuilder().setKey(new IdEntriesKey(idKey))
+ .setIdKey(idKey).setIdValue(newIdVal).build();
+ }
+
+ protected static DelayedIdEntries createDelayedIdEntry(long idValue, long delayTime) {
+ return new DelayedIdEntriesBuilder()
+ .setId(idValue)
+ .setReadyTimeSec(delayTime).build();
+ }
+
+ protected static IdPool createGlobalPool(String poolName, long low, long high, long blockSize) {
+ AvailableIdsHolder availableIdsHolder = createAvailableIdsHolder(low, high, low - 1);
+ ReleasedIdsHolder releasedIdsHolder = createReleasedIdsHolder(DEFAULT_AVAILABLE_ID_COUNT, 0);
+ int size = (int) blockSize;
+ return new IdPoolBuilder().setKey(new IdPoolKey(poolName))
+ .setBlockSize(size).setPoolName(poolName)
+ .setAvailableIdsHolder(availableIdsHolder)
+ .setReleasedIdsHolder(releasedIdsHolder).build();
+ }
+
+ protected static AvailableIdsHolder createAvailableIdsHolder(long low, long high, long cursor) {
+ AvailableIdsHolder availableIdsHolder = new AvailableIdsHolderBuilder()
+ .setStart(low).setEnd(high).setCursor(cursor).build();
+ return availableIdsHolder;
+ }
+
+ protected static ReleasedIdsHolder createReleasedIdsHolder(long availableIdCount, long delayTime) {
+ ReleasedIdsHolder releasedIdsHolder = new ReleasedIdsHolderBuilder()
+ .setAvailableIdCount(availableIdCount)
+ .setDelayedTimeSec(delayTime).build();
+ return releasedIdsHolder;
+ }
+
+ protected static InstanceIdentifier<IdPool> getIdPoolInstance(String poolName) {
+ InstanceIdentifier.InstanceIdentifierBuilder<IdPool> idPoolBuilder = InstanceIdentifier
+ .builder(IdPools.class).child(IdPool.class,
+ new IdPoolKey(poolName));
+ InstanceIdentifier<IdPool> id = idPoolBuilder.build();
+ return id;
+ }
+
+ protected static InstanceIdentifier<ReleasedIdsHolder> getReleasedIdsHolderInstance(String poolName) {
+ InstanceIdentifier.InstanceIdentifierBuilder<ReleasedIdsHolder> releasedIdsHolder = InstanceIdentifier
+ .builder(IdPools.class).child(IdPool.class,
+ new IdPoolKey(poolName)).child(ReleasedIdsHolder.class);
+ InstanceIdentifier<ReleasedIdsHolder> releasedIds = releasedIdsHolder.build();
+ return releasedIds;
+ }
+
+ /**
+ * Changes made to releasedIds are not persisted in the datastore.
+ * @param releasedIds
+ * @return
+ */
+ protected static long getIdFromReleaseIdsIfAvailable(ReleasedIdsHolderBuilder releasedIds) {
+ List<DelayedIdEntries> delayedIdEntries = releasedIds.getDelayedIdEntries();
+ long newIdValue = -1;
+ if (delayedIdEntries != null && !delayedIdEntries.isEmpty()) {
+ processDelayList(releasedIds);
+ if (releasedIds.getAvailableIdCount() > 0) {
+ DelayedIdEntries delayedIdEntry= delayedIdEntries.get(0);
+ newIdValue = delayedIdEntry.getId();
+ delayedIdEntries.remove(delayedIdEntry);
+ releasedIds.setDelayedIdEntries(delayedIdEntries);
+ releasedIds.setAvailableIdCount(releasedIds.getAvailableIdCount() - 1);
+ }
+ }
+ return newIdValue;
+ }
+
+ /**
+ * Changes made to availableIds are not persisted to datastore.
+ * @param availableIds
+ * @return
+ */
+ protected static long getIdFromAvailableIds(AvailableIdsHolderBuilder availableIds) {
+ long newIdValue = -1;
+ if (availableIds != null && isIdAvailable(availableIds)) {
+ newIdValue = availableIds.getCursor() + 1;
+ availableIds.setCursor(newIdValue);
+ }
+ return newIdValue;
+ }
+
+ protected static boolean isIdAvailable(AvailableIdsHolderBuilder availableIds) {
+ if (availableIds.getCursor() != null && availableIds.getEnd() != null)
+ return availableIds.getCursor() < availableIds.getEnd();
+ return false;
+ }
+
+ protected static String getLocalPoolName(String poolName) {
+ return (poolName + "." + BLADE_ID);
+ }
+
+ protected static IdPool createLocalIdPool(String localPoolName, IdPool parentIdPool) {
+ ReleasedIdsHolder releasedIdsHolder = createReleasedIdsHolder(DEFAULT_AVAILABLE_ID_COUNT, DEFAULT_DELAY_TIME);
+ return new IdPoolBuilder().setKey(new IdPoolKey(localPoolName))
+ .setPoolName(localPoolName)
+ .setParentPoolName(parentIdPool.getPoolName())
+ .setBlockSize(parentIdPool.getBlockSize())
+ .setReleasedIdsHolder(releasedIdsHolder).build();
+ }
+
+ protected static ChildPools createChildPool(String childPoolName) {
+ return new ChildPoolsBuilder().setKey(new ChildPoolsKey(childPoolName)).setChildPoolName(childPoolName).setLastAccessTime(System.currentTimeMillis() / 1000).build();
+ }
+
+ protected static AvailableIdsHolderBuilder getAvailableIdsHolderBuilder(IdPool pool) {
+ AvailableIdsHolder availableIds = pool.getAvailableIdsHolder();
+ if (availableIds != null )
+ return new AvailableIdsHolderBuilder(availableIds);
+ return new AvailableIdsHolderBuilder();
+ }
+
+ protected static ReleasedIdsHolderBuilder getReleaseIdsHolderBuilder(IdPool pool) {
+ ReleasedIdsHolder releasedIds = pool.getReleasedIdsHolder();
+ if (releasedIds != null)
+ return new ReleasedIdsHolderBuilder(releasedIds);
+ return new ReleasedIdsHolderBuilder();
+ }
+
+ /**
+ * Changes made to releaseIds are not persisted to the Datastore. Method invoking should ensure that releaseIds gets persisted.
+ * @param releasedIds
+ */
+ protected static void processDelayList(ReleasedIdsHolderBuilder releasedIds) {
+ List<DelayedIdEntries> delayedIdEntries = releasedIds.getDelayedIdEntries();
+ if (delayedIdEntries == null)
+ return;
+ long availableIdCount = releasedIds.getAvailableIdCount() == null ? 0 : releasedIds.getAvailableIdCount();
+ int index = (int) availableIdCount;
+ long currentTimeSec = System.currentTimeMillis() / 1000;
+ DelayedIdEntry delayedIdEntry;
+ while (index < delayedIdEntries.size()) {
+ delayedIdEntry = delayedIdEntries.get(index);
+ if (delayedIdEntry.getReadyTimeSec() > currentTimeSec) {
+ break;
+ }
+ availableIdCount++;
+ index++;
+ }
+ releasedIds.setAvailableIdCount(availableIdCount);
+ }
+
+ /**
+ * Changes made to the parameters passed are not persisted to the Datastore. Method invoking should ensure that these gets persisted.
+ * @param releasedIdsChild
+ * @param releasedIdsParent
+ * @param idCountToBeFreed
+ */
+ protected static void freeExcessAvailableIds(ReleasedIdsHolderBuilder releasedIdsChild, ReleasedIdsHolderBuilder releasedIdsParent, int idCountToBeFreed) {
+ List<DelayedIdEntries> existingDelayedIdEntriesInParent = releasedIdsParent.getDelayedIdEntries();
+ List<DelayedIdEntries> delayedIdEntriesChild = releasedIdsChild.getDelayedIdEntries();
+ long availableIdCountParent = releasedIdsParent.getAvailableIdCount();
+ long availableIdCountChild = releasedIdsChild.getAvailableIdCount();
+ if (existingDelayedIdEntriesInParent == null) {
+ existingDelayedIdEntriesInParent = new LinkedList<>();
+ }
+ idCountToBeFreed = Math.min(idCountToBeFreed, delayedIdEntriesChild.size());
+ for (int index = 0; index < idCountToBeFreed; index++) {
+ existingDelayedIdEntriesInParent.add(delayedIdEntriesChild.get(0));
+ delayedIdEntriesChild.remove(0);
+ }
+ releasedIdsChild.setDelayedIdEntries(delayedIdEntriesChild).setAvailableIdCount(availableIdCountChild - idCountToBeFreed);
+ releasedIdsParent.setDelayedIdEntries(existingDelayedIdEntriesInParent).setAvailableIdCount(availableIdCountParent + idCountToBeFreed);
+ }
+
+ protected static InstanceIdentifier<IdEntries> getIdEntriesInstanceIdentifier(String poolName, String idKey) {
+ InstanceIdentifier<IdEntries> idEntries = InstanceIdentifier
+ .builder(IdPools.class).child(IdPool.class,
+ new IdPoolKey(poolName)).child(IdEntries.class, new IdEntriesKey(idKey)).build();
+ return idEntries;
+ }
+
+ protected static InstanceIdentifier<ChildPools> getChildPoolsInstanceIdentifier(String poolName, String localPoolName) {
+ InstanceIdentifier<ChildPools> childPools = InstanceIdentifier
+ .builder(IdPools.class)
+ .child(IdPool.class, new IdPoolKey(poolName))
+ .child(ChildPools.class, new ChildPoolsKey(localPoolName)).build();
+ return childPools;
+ }
+
+ protected static long computeBlockSize(long low, long high) {
+ long blockSize;
+
+ long diff = high - low;
+ if (diff > DEFAULT_BLOCK_SIZE_DIFF) {
+ blockSize = diff / DEFAULT_BLOCK_SIZE_DIFF;
+ } else {
+ blockSize = 1;
+ }
+ return blockSize;
+ }
+
+ public static long getAvailableIdsCount(AvailableIdsHolderBuilder availableIds) {
+ if(availableIds != null && isIdAvailable(availableIds)) {
+ return availableIds.getEnd() - availableIds.getCursor();
+ }
+ return 0;
+ }
+
+ public static void lockPool(LockManagerService lockManager, String poolName) {
+ LockInput input = new LockInputBuilder().setLockName(poolName).build();
+ Future<RpcResult<Void>> result = lockManager.lock(input);
+ try {
+ if ((result != null) && (result.get().isSuccessful())) {
+ LOGGER.debug("Acquired lock {}", poolName);
+ } else {
+ throw new RuntimeException(String.format("Unable to getLock for pool %s", poolName));
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOGGER.error("Unable to getLock for pool {}", poolName);
+ throw new RuntimeException(String.format("Unable to getLock for pool %s", poolName), e.getCause());
+ }
+ }
+
+ public static void unlockPool(LockManagerService lockManager, String poolName) {
+ UnlockInput input = new UnlockInputBuilder().setLockName(poolName).build();
+ Future<RpcResult<Void>> result = lockManager.unlock(input);
+ try {
+ if ((result != null) && (result.get().isSuccessful())) {
+ LOGGER.debug("Unlocked {}", poolName);
+ } else {
+ LOGGER.debug("Unable to unlock pool {}", poolName);
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOGGER.error("Unable to unlock for pool {}", poolName);
+ throw new RuntimeException(String.format("Unable to unlock pool %s", poolName), e.getCause());
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.idmanager.impl.rev150325;
+
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.idmanager.IdManagerServiceProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
+
+public class IdmanagerImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.idmanager.impl.rev150325.AbstractIdmanagerImplModule {
+ public IdmanagerImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public IdmanagerImplModule(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.idmanager.impl.rev150325.IdmanagerImplModule oldModule, java.lang.AutoCloseable oldInstance) {
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+ LockManagerService lockManagerService = getRpcRegistryDependency().getRpcService(LockManagerService.class);
+ IdManagerServiceProvider provider = new IdManagerServiceProvider(getRpcRegistryDependency());
+ provider.setLockManager(lockManagerService);
+ getBrokerDependency().registerProvider(provider);
+ return provider;
+ }
+
+ @Override
+ public void customValidation() {
+ // add custom validation form module attributes here.
+ }
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: idmanager-impl yang module local name: idmanager-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Fri Apr 03 08:37:12 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.idmanager.impl.rev150325;
+public class IdmanagerImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.idmanager.impl.rev150325.AbstractIdmanagerImplModuleFactory {
+
+}
--- /dev/null
+module idmanager-impl {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:idmanager:impl";
+ prefix "idmanager-impl";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
+
+ description
+ "Service definition for idmanager project";
+
+ revision "2015-03-25" {
+ description
+ "Initial revision";
+ }
+
+ identity idmanager-impl {
+ base config:module-type;
+ config:java-name-prefix IdmanagerImpl;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case idmanager-impl {
+ when "/config:modules/config:module/config:type = 'idmanager-impl'";
+ container broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-broker-osgi-registry;
+ }
+ }
+ }
+ container rpc-registry {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-rpc-registry;
+ }
+ }
+ }
+
+ }
+ }
+}
--- /dev/null
+package org.opendaylight.idmanager.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Future;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+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.idmanager.IdManager;
+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;
+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.DeleteIdPoolInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.DeleteIdPoolInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
+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.IdPoolBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolderBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPools;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPoolsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPoolsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntriesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolderBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.UnlockInput;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.net.InetAddresses;
+import com.google.common.util.concurrent.Futures;
+
+
+@RunWith(MockitoJUnitRunner.class)
+public class IdManagerTest {
+ private static final Logger LOG = LoggerFactory.getLogger(IdManagerTest.class);
+ private static int BLADE_ID;
+ static {
+ try {
+ BLADE_ID = InetAddresses.coerceToInteger(InetAddress.getLocalHost());
+ } catch (Exception e) {
+ LOG.error("IdManager - Exception - {}", e.getMessage());
+ }
+ }
+
+ Map<InstanceIdentifier<?>,DataObject> configDataStore = new HashMap<>();
+ @Mock DataBroker dataBroker;
+ @Mock ReadOnlyTransaction mockReadTx;
+ @Mock WriteTransaction mockWriteTx;
+ @Mock LockManagerService lockManager;
+ Future<RpcResult<Void>> rpcResult;
+ IdManager idManager;
+ IdPool globalIdPool;
+ InstanceIdentifier<IdPool> identifier;
+ InstanceIdentifier<IdPool> childIdentifier;
+ InstanceIdentifier<ChildPools> childPoolIdentifier;
+ String globalPoolName = "test-pool";
+ String localPoolName = new StringBuilder(globalPoolName).append(".").append(BLADE_ID).toString();
+ String idKey = "test-key1";
+ int idStart = 100;
+ int idEnd = 200;
+ int blockSize = 2;
+ String idKey2 = "test-key2";
+ int idValue = 25;
+
+ @Before
+ public void setUp() throws Exception {
+
+ idManager = new IdManager(dataBroker);
+ idManager.setLockManager(lockManager);
+ setupMocks();
+ }
+
+ private void setupMocks() {
+ globalIdPool = buildGlobalIdPool(globalPoolName, idStart, idEnd, blockSize, buildChildPool(localPoolName)).build();
+ identifier = buildInstanceIdentifier(globalPoolName);
+ childIdentifier = buildInstanceIdentifier(localPoolName);
+ childPoolIdentifier = buildChildPoolInstanceIdentifier(globalPoolName, localPoolName);
+ when(dataBroker.newReadOnlyTransaction()).thenReturn(mockReadTx);
+ when(dataBroker.newWriteOnlyTransaction()).thenReturn(mockWriteTx);
+ when(lockManager.lock(any(LockInput.class))).thenReturn(Futures.immediateFuture(RpcResultBuilder.<Void>success().build()));
+ when(lockManager.unlock(any(UnlockInput.class))).thenReturn(Futures.immediateFuture(RpcResultBuilder.<Void>success().build()));
+ doReturn(Futures.immediateCheckedFuture(null)).when(mockWriteTx).submit();
+ doReturn(Futures.immediateCheckedFuture(null)).when(mockReadTx).read(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class));
+ }
+
+ @Test
+ public void testCreateIdPool() throws Exception
+ {
+ CreateIdPoolInput createPoolTest = buildCreateIdPool(globalPoolName, idStart, idEnd);
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, identifier);
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, childIdentifier);
+ Future<RpcResult<Void>> result = idManager.createIdPool(createPoolTest);
+ DataObject dataObject;
+ IdPool pool;
+ assertTrue(result.get().isSuccessful());
+ assertEquals(0,configDataStore.size());
+ dataObject = configDataStore.get(childIdentifier);
+ if (dataObject instanceof IdPool) {
+ pool = (IdPool) dataObject;
+ assertEquals(localPoolName, pool.getPoolName());
+ assertEquals(createPoolTest.getPoolName(), pool.getParentPoolName());
+ assertEquals(null, pool.getAvailableIdsHolder());
+ assertEquals(30, pool.getReleasedIdsHolder().getDelayedTimeSec().longValue());
+ assertEquals(0, pool.getReleasedIdsHolder().getAvailableIdCount().longValue());
+ assertEquals(blockSize, pool.getBlockSize().longValue());
+ }
+ dataObject = configDataStore.get(identifier);
+ if (dataObject instanceof IdPool) {
+ pool = (IdPool) dataObject;
+ assertEquals(createPoolTest.getPoolName(), pool.getPoolName());
+ assertEquals(0, pool.getReleasedIdsHolder().getDelayedTimeSec().longValue());
+ assertEquals(0, pool.getReleasedIdsHolder().getAvailableIdCount().longValue());
+ assertEquals(createPoolTest.getLow(), pool.getAvailableIdsHolder().getStart());
+ assertEquals(createPoolTest.getHigh(), pool.getAvailableIdsHolder().getEnd());
+ assertEquals(createPoolTest.getLow() - 1, pool.getAvailableIdsHolder().getCursor().intValue());
+ assertEquals(blockSize, pool.getBlockSize().longValue());
+ }
+ dataObject = configDataStore.get(childPoolIdentifier);
+ if (dataObject instanceof ChildPools) {
+ ChildPools childPool = (ChildPools) dataObject;
+ assertEquals(localPoolName, childPool.getChildPoolName());
+ }
+ }
+
+ @Test
+ public void testAllocateId() throws Exception
+ {
+ AllocateIdInput allocateIdInput = buildAllocateId(globalPoolName, idKey);
+ List<IdEntries> idEntries = new ArrayList<IdEntries>();
+ idEntries.add(buildIdEntry(idKey2, idValue));
+ Optional<IdPool> expectedLocalPool = Optional.of(buildLocalIdPool(blockSize, localPoolName, globalPoolName).build());
+ IdPool globalIdPool = buildGlobalIdPool(globalPoolName, idStart, idEnd, blockSize, buildChildPool(localPoolName)).setIdEntries(idEntries).build();
+ Optional<IdPool> expectedGlobalPool = Optional.of(globalIdPool);
+ doReturn(Futures.immediateCheckedFuture(expectedGlobalPool)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, identifier);
+ doReturn(Futures.immediateCheckedFuture(expectedLocalPool)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, childIdentifier);
+ InstanceIdentifier<IdEntries> idEntriesIdentifier = buildIdEntriesIdentifier(idKey);
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, idEntriesIdentifier);
+ InstanceIdentifier<AvailableIdsHolder> availableIdsIdentifier = buildAvailbaleIdsIdentifier(globalPoolName);
+
+ Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(allocateIdInput);
+ assertTrue(result.get().isSuccessful());
+ assertEquals(0,configDataStore.size());
+ DataObject dataObject = configDataStore.get(childIdentifier);
+ if (dataObject instanceof IdPool) {
+ IdPool pool = (IdPool) dataObject;
+ assertEquals(localPoolName, pool.getPoolName());
+ assertEquals(idStart, pool.getAvailableIdsHolder().getStart().intValue());
+ assertEquals(idStart + blockSize - 1 , pool.getAvailableIdsHolder().getEnd().intValue());
+ assertEquals(idStart, pool.getAvailableIdsHolder().getCursor().intValue());
+ }
+ dataObject = configDataStore.get(identifier);
+ if (dataObject instanceof IdPool) {
+ IdPool parentPool = (IdPool) dataObject;
+ assertEquals(2, parentPool.getIdEntries().size());
+ }
+ dataObject = configDataStore.get(availableIdsIdentifier);
+ if (dataObject instanceof AvailableIdsHolder) {
+ AvailableIdsHolder availableIds = (AvailableIdsHolder) dataObject;
+ assertEquals(idEnd, availableIds.getEnd().intValue());
+ assertEquals(idStart, availableIds.getStart().intValue());
+ assertEquals(idStart + blockSize - 1, availableIds.getCursor().intValue());
+ }
+ }
+
+ @Test
+ public void testReleaseId() throws Exception {
+ ReleaseIdInput releaseIdInput = createReleaseIdInput(globalPoolName, idKey);
+ List<IdEntries> idEntries = new ArrayList<IdEntries>();
+ idEntries.add(buildIdEntry(idKey, idValue));
+ Optional<IdPool> expectedLocalPool = Optional.of(buildLocalIdPool(blockSize, localPoolName, globalPoolName).build());
+ IdPool globalIdPool = buildGlobalIdPool(globalPoolName, idStart, idEnd, blockSize, buildChildPool(localPoolName)).setIdEntries(idEntries).build();
+ Optional<IdPool> expectedGlobalPool = Optional.of(globalIdPool);
+ doReturn(Futures.immediateCheckedFuture(expectedGlobalPool)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, identifier);
+ doReturn(Futures.immediateCheckedFuture(expectedLocalPool)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, childIdentifier);
+ InstanceIdentifier<IdEntries> idEntriesIdentifier = buildIdEntriesIdentifier(idKey);
+ Optional<IdEntries> expectedIdEntry = Optional.of(buildIdEntry(idKey, idValue));
+ doReturn(Futures.immediateCheckedFuture(expectedIdEntry)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, idEntriesIdentifier);
+ Future<RpcResult<Void>> result = idManager.releaseId(releaseIdInput);
+ assertTrue(result.get().isSuccessful());
+ assertEquals(0, configDataStore.size());
+ DataObject idPoolVal = configDataStore.get(childIdentifier);
+ if (idPoolVal instanceof IdPool) {
+ IdPool pool = (IdPool) idPoolVal;
+ assertEquals(0, pool.getReleasedIdsHolder().getAvailableIdCount().intValue());
+ assertEquals(idValue, pool.getReleasedIdsHolder().getDelayedIdEntries().get(0).getId().intValue());
+ }
+ idPoolVal = configDataStore.get(identifier);
+ if (idPoolVal instanceof IdPool) {
+ IdPool parentPool = (IdPool) idPoolVal;
+ assertEquals(0, parentPool.getIdEntries().size());
+ }
+ }
+
+ @Test
+ public void testCleanupReleasedIds() throws Exception {
+ AllocateIdInput allocateIdInput = buildAllocateId(globalPoolName, idKey2);
+ Optional<ReleasedIdsHolder> expected = Optional.of(createReleasedIdsHolder(0, null, 0));
+ long[] excessIds = new long[] { 1, 2, 3, 4, 5 };
+ List<IdEntries> idEntries = new ArrayList<IdEntries>();
+ idEntries.add(buildIdEntry(idKey2, idValue));
+ ReleasedIdsHolder excessReleasedIds = createReleasedIdsHolder(0, buildDelayedIdEntries(excessIds), (long) 30);
+ Optional<IdPool> expectedLocalPool = Optional.of(buildLocalIdPool(blockSize, localPoolName, globalPoolName)
+ .setReleasedIdsHolder(excessReleasedIds)
+ .build());
+ InstanceIdentifier<ReleasedIdsHolder> releaseIdsIdentifier = buildReleaseIdsIdentifier(globalPoolName);
+ IdPool globalIdPool = buildGlobalIdPool(globalPoolName, idStart, idEnd, blockSize, buildChildPool(localPoolName)).setIdEntries(idEntries).build();
+ Optional<IdPool> expectedGlobalPool = Optional.of(globalIdPool);
+ doReturn(Futures.immediateCheckedFuture(expectedGlobalPool)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, identifier);
+ doReturn(Futures.immediateCheckedFuture(expected)).when(mockReadTx)
+ .read(LogicalDatastoreType.CONFIGURATION, releaseIdsIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedLocalPool)).when(
+ mockReadTx).read(LogicalDatastoreType.CONFIGURATION,
+ childIdentifier);
+ InstanceIdentifier<IdEntries> idEntriesIdentifier = buildIdEntriesIdentifier(idKey2);
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(
+ mockReadTx).read(LogicalDatastoreType.CONFIGURATION,
+ idEntriesIdentifier);
+
+ Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(allocateIdInput);
+ assertTrue(result.get().isSuccessful());
+ assertEquals(0, configDataStore.size());
+ DataObject dataObject = configDataStore.get(childIdentifier);
+ if (dataObject instanceof IdPool) {
+ IdPool pool = (IdPool) dataObject;
+ assertEquals(localPoolName, pool.getPoolName());
+ assertEquals(excessIds.length - 3, pool.getReleasedIdsHolder().getAvailableIdCount().intValue());
+ }
+ dataObject = configDataStore.get(identifier);
+ if (dataObject instanceof IdPool) {
+ IdPool parentPool = (IdPool) dataObject;
+ assertEquals(2, parentPool.getIdEntries().size());
+ }
+ dataObject = configDataStore.get(releaseIdsIdentifier);
+ if (dataObject instanceof ReleasedIdsHolder) {
+ ReleasedIdsHolder releasedIds = (ReleasedIdsHolder) dataObject;
+ assertEquals(2, releasedIds.getAvailableIdCount().intValue());
+ assertEquals(2, releasedIds.getDelayedIdEntries().size());
+ }
+ }
+
+ @Test
+ public void testAllocateIdBlockFromReleasedIds() throws Exception {
+ AllocateIdInput allocateIdInput = buildAllocateId(globalPoolName, globalPoolName);
+ List<DelayedIdEntries> delayedIdEntries = buildDelayedIdEntries(new long[] {1, 2, 3});
+ ReleasedIdsHolder expectedReleasedIds = createReleasedIdsHolder(3, delayedIdEntries , 0);
+ IdPool globalIdPool = buildGlobalIdPool(globalPoolName, idStart, idEnd, blockSize, buildChildPool(localPoolName)).setReleasedIdsHolder(expectedReleasedIds).build();
+ Optional<IdPool> expected = Optional.of(globalIdPool);
+ Optional<IdPool> expectedLocalPool = Optional.of(buildLocalIdPool(blockSize, localPoolName, globalPoolName).build());
+ doReturn(Futures.immediateCheckedFuture(expected)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, identifier);
+ doReturn(Futures.immediateCheckedFuture(expectedLocalPool)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, childIdentifier);
+ InstanceIdentifier<IdEntries> idEntriesIdentifier = buildIdEntriesIdentifier(globalPoolName);
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, idEntriesIdentifier);
+ InstanceIdentifier<ReleasedIdsHolder> releaseIdsIdentifier = buildReleaseIdsIdentifier(globalPoolName);
+
+ Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(allocateIdInput);
+ assertTrue(result.get().isSuccessful());
+ assertEquals(0,configDataStore.size());
+ DataObject dataObject = configDataStore.get(childIdentifier);
+ if (dataObject instanceof IdPool) {
+ IdPool pool = (IdPool) dataObject;
+ assertEquals(localPoolName, pool.getPoolName());
+ assertEquals(1, pool.getReleasedIdsHolder().getDelayedIdEntries().size());
+ assertEquals(1, pool.getReleasedIdsHolder().getAvailableIdCount().intValue());
+ }
+ dataObject = configDataStore.get(identifier);
+ if (dataObject instanceof IdPool) {
+ IdPool parentPool = (IdPool) dataObject;
+ assertEquals(1, parentPool.getIdEntries().size());
+ }
+ dataObject = configDataStore.get(releaseIdsIdentifier);
+ if (dataObject instanceof ReleasedIdsHolder) {
+ ReleasedIdsHolder releasedIds = (ReleasedIdsHolder) dataObject;
+ assertEquals(1, releasedIds.getAvailableIdCount().intValue());
+ assertEquals(1, releasedIds.getDelayedIdEntries().size());
+ }
+ }
+
+ @Test
+ public void testDeletePool() throws Exception {
+ IdPool globalIdPool = buildGlobalIdPool(globalPoolName, idStart, idEnd, blockSize, buildChildPool(localPoolName)).build();
+ Optional<IdPool> expected = Optional.of(globalIdPool);
+ Optional<IdPool> expectedLocalPool = Optional.of(buildLocalIdPool(blockSize, localPoolName, globalPoolName).build());
+ doReturn(Futures.immediateCheckedFuture(expected)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, identifier);
+ doReturn(Futures.immediateCheckedFuture(expectedLocalPool)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, childIdentifier);
+ DeleteIdPoolInput deleteIdPoolInput = createDeleteIdPoolInput(globalPoolName);
+ configDataStore.put(childIdentifier, null);
+ configDataStore.put(identifier, null);
+ Future<RpcResult<Void>> result = idManager.deleteIdPool(deleteIdPoolInput);
+ assertTrue(result.get().isSuccessful());
+ assertEquals(2, configDataStore.size());
+ }
+
+ private InstanceIdentifier<ReleasedIdsHolder> buildReleaseIdsIdentifier(
+ String poolName) {
+ InstanceIdentifier<ReleasedIdsHolder> releasedIds = InstanceIdentifier
+ .builder(IdPools.class).child(IdPool.class,
+ new IdPoolKey(poolName)).child(ReleasedIdsHolder.class).build();
+ return releasedIds;
+ }
+
+ private InstanceIdentifier<AvailableIdsHolder> buildAvailbaleIdsIdentifier(
+ String poolName) {
+ InstanceIdentifier<AvailableIdsHolder> availableIds = InstanceIdentifier
+ .builder(IdPools.class).child(IdPool.class,
+ new IdPoolKey(poolName)).child(AvailableIdsHolder.class).build();
+ return availableIds;
+ }
+
+ private InstanceIdentifier<ChildPools> buildChildPoolInstanceIdentifier(String poolName, String childPoolName) {
+ InstanceIdentifier<ChildPools> childPool = InstanceIdentifier
+ .builder(IdPools.class).child(IdPool.class,
+ new IdPoolKey(poolName)).child(ChildPools.class, new ChildPoolsKey(childPoolName)).build();
+ return childPool;
+ }
+
+ private ReleaseIdInput createReleaseIdInput(String poolName, String idKey) {
+ return new ReleaseIdInputBuilder().setIdKey(idKey).setPoolName(poolName).build();
+ }
+
+ private IdEntries buildIdEntry(String idKey, long idValue) {
+ return new IdEntriesBuilder().setIdKey(idKey).setIdValue(idValue).build();
+ }
+
+ private InstanceIdentifier<IdEntries> buildIdEntriesIdentifier(String idKey) {
+ InstanceIdentifier.InstanceIdentifierBuilder<IdEntries> idEntriesBuilder = identifier
+ .builder().child(IdEntries.class, new IdEntriesKey(idKey));
+ InstanceIdentifier<IdEntries> idEntry = idEntriesBuilder.build();
+ return idEntry;
+ }
+
+ private CreateIdPoolInput buildCreateIdPool(String poolName, long low, long high) {
+ CreateIdPoolInput createPool = new CreateIdPoolInputBuilder().setPoolName(poolName)
+ .setLow(low)
+ .setHigh(high)
+ .build();
+ return createPool;
+ }
+
+ private IdPoolBuilder buildGlobalIdPool(String poolName, long idStart, long poolSize, int blockSize, List<ChildPools> childPools) {
+ AvailableIdsHolder availableIdsHolder = createAvailableIdsHolder(idStart, poolSize, idStart - 1);
+ ReleasedIdsHolder releasedIdsHolder = createReleasedIdsHolder(0, null, 0);
+ return new IdPoolBuilder().setKey(new IdPoolKey(poolName))
+ .setPoolName(poolName)
+ .setBlockSize(blockSize)
+ .setChildPools(childPools)
+ .setAvailableIdsHolder(availableIdsHolder)
+ .setReleasedIdsHolder(releasedIdsHolder);
+ }
+
+ private IdPoolBuilder buildLocalIdPool(int blockSize, String localPoolName, String parentPoolName) {
+ ReleasedIdsHolder releasedIdsHolder = createReleasedIdsHolder(0, null, (long) 30);
+ return new IdPoolBuilder().setBlockSize(blockSize)
+ .setKey(new IdPoolKey(localPoolName))
+ .setParentPoolName(parentPoolName)
+ .setReleasedIdsHolder(releasedIdsHolder);
+ }
+
+ private AllocateIdInput buildAllocateId(String poolName, String idKey) {
+ AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName)
+ .setIdKey(idKey).build();
+ return getIdInput;
+ }
+
+ private InstanceIdentifier<IdPool> buildInstanceIdentifier(String poolName) {
+ InstanceIdentifier.InstanceIdentifierBuilder<IdPool> idBuilder =
+ InstanceIdentifier.builder(IdPools.class).child(IdPool.class, new IdPoolKey(poolName));
+ InstanceIdentifier<IdPool> id = idBuilder.build();
+ return id;
+ }
+
+ private AvailableIdsHolder createAvailableIdsHolder(long low, long high, long cursor) {
+ AvailableIdsHolder availableIdsHolder = new AvailableIdsHolderBuilder()
+ .setStart(low).setEnd(high).setCursor(cursor).build();
+ return availableIdsHolder;
+ }
+
+ private ReleasedIdsHolder createReleasedIdsHolder(long availableIdCount, List<DelayedIdEntries> delayedIdEntries, long delayTime) {
+ ReleasedIdsHolder releasedIdsHolder = new ReleasedIdsHolderBuilder()
+ .setAvailableIdCount(availableIdCount)
+ .setDelayedIdEntries(delayedIdEntries)
+ .setDelayedTimeSec(delayTime).build();
+ return releasedIdsHolder;
+ }
+
+ private DeleteIdPoolInput createDeleteIdPoolInput(String poolName) {
+ return new DeleteIdPoolInputBuilder().setPoolName(poolName).build();
+ }
+
+ private List<DelayedIdEntries> buildDelayedIdEntries(long[] idValues) {
+ List<DelayedIdEntries> delayedIdEntriesList = new ArrayList<DelayedIdEntries>();
+ for (long idValue : idValues) {
+ DelayedIdEntries delayedIdEntries = new DelayedIdEntriesBuilder().setId(idValue).setReadyTimeSec(0L).build();
+ delayedIdEntriesList.add(delayedIdEntries);
+ }
+ return delayedIdEntriesList;
+ }
+
+ private List<ChildPools> buildChildPool(String childPoolName) {
+ ChildPools childPools = new ChildPoolsBuilder().setChildPoolName(childPoolName).build();
+ List<ChildPools> childPoolsList = new ArrayList<ChildPools>();
+ childPoolsList.add(childPools);
+ return childPoolsList;
+ }
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>idmanager-aggregator</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <name>idmanager</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>idmanager-api</module>
+ <module>idmanager-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>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>interfacemgr-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>org.opendaylight.vpnservice</groupId>
+ <artifactId>mdsalutil-api</artifactId>
+ <version>${vpns.mdsalutil.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.ovsdb</groupId>
+ <artifactId>southbound-api</artifactId>
+ <version>${vpns.ovsdb.version}</version>
+ </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.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) 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,
+ * 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,
+ MPLS_OVER_GRE,
+ 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) 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,
+ * 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 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.services.info.BoundServicesKey;
+
+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 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 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.util.List;
+import java.util.ArrayList;
+
+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;
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.vpnservice.interfacemgr.interfaces;
+
+import java.math.BigInteger;
+import java.util.List;
+
+import org.opendaylight.vpnservice.interfacemgr.exceptions.InterfaceAlreadyExistsException;
+import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
+import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
+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.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.services.info.BoundServices;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
+
+@Deprecated
+public interface IInterfaceManager {
+ @Deprecated
+ public Long getPortForInterface(String ifName);
+
+ @Deprecated
+ public BigInteger getDpnForInterface(String ifName);
+
+ @Deprecated
+ public BigInteger getDpnForInterface(Interface intrf);
+
+ @Deprecated
+ public String getEndpointIpForDpn(BigInteger dpnId);
+
+ @Deprecated
+ public List<ActionInfo> getInterfaceEgressActions(String ifName);
+
+ @Deprecated
+ public Long getPortForInterface(Interface intf);
+
+ public InterfaceInfo getInterfaceInfo(String intInfo);
+
+ public InterfaceInfo getInterfaceInfoFromOperationalDataStore(String interfaceName, InterfaceInfo.InterfaceType interfaceType);
+ public InterfaceInfo getInterfaceInfoFromOperationalDataStore(String interfaceName);
+
+ public void createVLANInterface(String interfaceName, String portName, BigInteger dpId, Integer vlanId,
+ String description, IfL2vlan.L2vlanMode l2vlanMode);
+ public void bindService(String interfaceName, BoundServices serviceInfo);
+ public void unbindService(String interfaceName, BoundServices serviceInfo);
+ List<Interface> getVlanInterfaces();
+ List<Interface> getVxlanInterfaces();
+}
\ 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;
+ }
+ }
+ }
+
+}
--- /dev/null
+module odl-interface-meta {
+ namespace "urn:opendaylight:vpnservice:interfacemgr:meta";
+ prefix "odlifmeta";
+
+ import ovsdb {
+ prefix southbound; revision-date "2015-01-05";
+ }
+
+ revision "2015-10-07" {
+ description "ODL rendering specific Interface Manager Meta Module";
+ }
+
+ container bridge-interface-info {
+ description "Contains the list of dpns along with the tunnel interfaces configured on them.";
+
+ list bridge-entry {
+ key dpid;
+ leaf dpid {
+ type uint64;
+ }
+
+ list bridge-interface-entry {
+ key interface-name;
+ leaf interface-name {
+ type string;
+ }
+ }
+ }
+ }
+
+ container bridge-ref-info {
+ config false;
+ description "The container that maps dpid with ovs bridge ref in the operational DS.";
+
+ list bridge-ref-entry {
+ key dpid;
+ leaf dpid {
+ type uint64;
+ }
+
+ leaf bridge-reference {
+ type southbound:ovsdb-bridge-ref;
+ description "This is the reference to an ovs bridge";
+ }
+ }
+ }
+
+ container interface-child-info {
+ description "The container of all Child-Interfaces for a given interface.";
+ list interface-parent-entry {
+ key parent-interface;
+ leaf parent-interface {
+ type string;
+ }
+
+ list interface-child-entry {
+ key child-interface;
+ leaf child-interface {
+ type string;
+ }
+ }
+ }
+ }
+
+ container if-indexes-interface-map {
+ config false;
+ list if-index-interface {
+ key if-index;
+ leaf if-index {
+ type int32;
+ }
+ leaf interface-name {
+ type string;
+ }
+ }
+ }
+
+ container interface-monitor-id-map {
+ config false;
+ list interface-monitor-id {
+ key interface-name;
+ leaf interface-name {
+ type string;
+ }
+ leaf-list monitor-id {
+ type uint32;
+ }
+ }
+ }
+
+ container monitor-id-interface-map {
+ config false;
+ list monitor-id-interface {
+ key monitor-id;
+ leaf monitor-id {
+ type uint32;
+ }
+ leaf interface-name {
+ type string;
+ }
+ }
+ }
+
+ container tunnel-instance-interface-map {
+ config false;
+ list tunnel-instance-interface {
+ key tunnel-instance-identifier;
+ leaf tunnel-instance-identifier {
+ type string;
+ }
+ leaf interface-name {
+ type string;
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+module odl-interface-rpc {
+ namespace "urn:opendaylight:vpnservice:interfacemgr:rpcs";
+ prefix "odlifrpc";
+
+ import ietf-inet-types {
+ prefix inet;
+ }
+
+ import odl-interface {
+ prefix odlif; revision-date 2015-03-31;
+ }
+
+ import opendaylight-inventory {
+ prefix inv; revision-date 2013-08-19;
+ }
+
+ import ietf-interfaces {
+ prefix if; revision-date 2014-05-08;
+ }
+
+ import opendaylight-action-types {prefix action;}
+ import opendaylight-flow-types {prefix offlow;revision-date "2013-10-26";}
+
+ revision "2015-10-03" {
+ description "ODL Specific Interface Manager Rpcs Module";
+ }
+
+ /* RPCs */
+
+ rpc get-dpid-from-interface {
+ description "used to retrieve dpid from interface name";
+ input {
+ leaf intf-name {
+ type string;
+ }
+ }
+ output {
+ leaf dpid {
+ type uint64;
+ }
+ }
+ }
+
+ rpc get-port-from-interface {
+ description "used to retrieve dpid from interface name";
+ input {
+ leaf intf-name {
+ type string;
+ }
+ }
+ output {
+ leaf dpid {
+ type uint64;
+ }
+ leaf portno {
+ type uint32;
+ }
+ leaf portname {
+ type string;
+ }
+ }
+ }
+
+ rpc get-egress-actions-for-interface {
+ description "used to retrieve group actions to use from interface name";
+ input {
+ leaf intf-name {
+ type string;
+ mandatory true;
+ }
+
+ leaf tunnel-key {
+ description "It can be VNI for VxLAN tunnel ifaces, Gre Key for GRE tunnels, etc.";
+ type uint32;
+ mandatory false;
+ }
+ }
+ output {
+ uses action:action-list;
+ }
+ }
+
+ rpc get-egress-instructions-for-interface {
+ description "used to retrieve flow instructions to use from interface name";
+ input {
+ leaf intf-name {
+ type string;
+ mandatory true;
+ }
+
+ leaf tunnel-key {
+ description "It can be VNI for VxLAN tunnel ifaces, Gre Key for GRE tunnels, etc.";
+ type uint32;
+ mandatory false;
+ }
+ }
+ output {
+ uses offlow:instruction-list;
+ }
+ }
+
+ rpc get-endpoint-ip-for-dpn {
+ description "to get the local ip of the tunnel/trunk interface";
+ input {
+ leaf dpid {
+ type uint64;
+ }
+ }
+ output {
+ leaf-list local-ips {
+ type inet:ip-address;
+ }
+ }
+ }
+
+ rpc get-interface-type {
+ description "to get the type of the interface(vlan/vxlan or gre)";
+ input {
+ leaf intf-name {
+ type string;
+ }
+ }
+ output {
+ leaf interface-type {
+ type identityref {
+ base if:interface-type;
+ }
+ }
+ }
+ }
+
+ rpc get-tunnel-type {
+ description "to get the type of the tunnel interface(vxlan or gre)";
+ input {
+ leaf intf-name {
+ type string;
+ }
+ }
+ output {
+ leaf tunnel-type {
+ type identityref {
+ base odlif:tunnel-type-base;
+ }
+ }
+ }
+ }
+
+
+ rpc get-nodeconnector-id-from-interface {
+ description "to get nodeconnector id associated with an interface";
+ input {
+ leaf intf-name {
+ type string;
+ }
+ }
+ output {
+ leaf nodeconnector-id {
+ type inv:node-connector-id;
+ }
+ }
+ }
+
+ rpc get-interface-from-if-index {
+ description "to get interface associated with an if-index";
+ input {
+ leaf if-index {
+ type int32;
+ }
+ }
+ output {
+ leaf interface-name {
+ type string;
+ }
+ }
+ }
+
+ rpc create-terminating-service-actions {
+ description "create the ingress terminating service table entries";
+ input {
+ leaf dpid {
+ type uint64;
+ }
+ leaf tunnel-key {
+ type uint64;
+ }
+ leaf interface-name {
+ type string;
+ }
+ uses offlow:instruction-list;
+ }
+ }
+
+ rpc remove-terminating-service-actions {
+ description "remove the ingress terminating service table entries";
+ input {
+ leaf dpid {
+ type uint64;
+ }
+ leaf interface-name {
+ type string;
+ }
+ leaf tunnel-key {
+ type uint64;
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+module interface-service-bindings {
+ namespace "urn:opendaylight:params:xml:ns:yang:servicebinding";
+ prefix ifservicebindings;
+
+ import opendaylight-flow-types {prefix offlow;revision-date "2013-10-26";}
+
+ import yang-ext {
+ prefix ext;
+ }
+
+ revision "2015-10-15" {
+ description "This YANG module defines the service binding model.";
+ }
+
+ identity service-type-base {
+ description "Base identity for all service-types";
+ }
+
+ identity service-type-flow-based {
+ description "Service type for flow-based services";
+ base service-type-base;
+ }
+
+ container service-bindings {
+ list services-info {
+ key interface-name;
+ leaf interface-name {
+ type string;
+ }
+
+ list bound-services {
+ key "service-priority";
+ max-elements "2";
+ min-elements "0";
+ leaf service-priority {
+ type uint8;
+ }
+
+ leaf service-type {
+ type identityref {
+ base service-type-base;
+ }
+ }
+
+ leaf service-name {
+ type string;
+ }
+ }
+ }
+ }
+
+ grouping service-openflow-info {
+ description "openflow specific information for services info.";
+
+ leaf dispatcher-table-id {
+ type uint8;
+ }
+
+ leaf flow-priority {
+ type uint16;
+ }
+
+ leaf flow-cookie {
+ type uint64;
+ }
+
+ uses offlow:instruction-list;
+ }
+
+ augment "/service-bindings/services-info/bound-services" {
+ ext:augment-identifier "stype-openflow";
+ when "service-type = 'service-type-flow-based'";
+ uses service-openflow-info;
+ }
+}
\ No newline at end of file
--- /dev/null
+module odl-interface {
+ namespace "urn:opendaylight:vpnservice:interfacemgr";
+
+ prefix "odlif";
+
+ import ietf-interfaces {
+ prefix if;
+ }
+
+ import yang-ext {
+ prefix ext;
+ }
+
+ import iana-if-type {
+ prefix ianaift;
+ }
+
+ import ietf-inet-types {
+ prefix inet;
+ revision-date "2010-09-24";
+ }
+
+ import opendaylight-inventory {
+ prefix inv; revision-date 2013-08-19;
+ }
+
+ import opendaylight-l2-types { prefix ethertype; revision-date "2013-08-27";}
+
+ import config {
+ prefix config; revision-date 2013-04-05;
+ }
+
+ revision "2015-03-31" {
+ description "ODL Interface Manager Module";
+ }
+
+ identity odl-interface {
+ status deprecated;
+ base "config:service-type";
+ config:java-class "org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager";
+ }
+
+ identity stacked-vlan {
+ base if:interface-type;
+ reference "Q-in-Q interface";
+ }
+
+ identity mpls {
+ base if:interface-type;
+ reference "MPLS interface";
+ }
+
+ /* Tunnel (GRE, VxLAN) logical port */
+ identity l3tunnel {
+ status deprecated;
+ base if:interface-type;
+ reference "l3 tunnel interface";
+ }
+
+ identity tunnel-type-base {
+ description "Base identity for all tunnel-types";
+ }
+
+ identity tunnel-type-vxlan {
+ description "Tunnel type for vxlan tunnels";
+ base tunnel-type-base;
+ }
+
+ identity tunnel-type-gre {
+ description "Tunnel type for gre tunnels";
+ base tunnel-type-base;
+ }
+
+ identity tunnel-type-mpls-over-gre {
+ description "Tunnel type for mpls over gre tunnels";
+ base tunnel-type-base;
+ }
+
+ /* base/common properties */
+ augment "/if:interfaces/if:interface" {
+ status deprecated;
+ ext:augment-identifier "base-ids";
+ leaf of-port-id {
+ type inv:node-connector-id;
+ description "can be a physical switch port or virtual switch port e.g. neutron port";
+ }
+ }
+
+ augment "/if:interfaces/if:interface" {
+ ext:augment-identifier "parent-refs";
+ leaf datapath-node-identifier {
+ type uint64;
+ description "can be a physical switch identifier (optional)";
+ }
+
+ leaf parent-interface {
+ type string;
+ description "can be a physical switch port or virtual switch port e.g. neutron port";
+ }
+
+ list node-identifier {
+ key "topology-id";
+ description "an identifier of the dependant underlying configuration protocol";
+ leaf "topology-id" {
+ type string;
+ description "can be ovsdb configuration protocol";
+ }
+ leaf "node-id" {
+ type string;
+ description "can be hwvtep configuration protocol";
+ }
+ }
+ }
+
+ /* interface type specific properties */
+
+ /* VLAN logical port */
+ augment "/if:interfaces/if:interface" {
+ ext:augment-identifier "if-l2vlan";
+ when "if:type = 'ianaift:l2vlan'";
+ leaf vlan-id {
+ type ethertype:vlan-id;
+ }
+
+ leaf l2vlan-mode {
+ description "The VLAN mode of the L2Vlan Interface.";
+ type enumeration {
+ enum "access" {
+ value 1;
+ description
+ "The VLAN mode access.";
+ }
+ enum "native-tagged" {
+ value 2;
+ description
+ "The VLAN mode native-tagged.";
+ }
+ enum "native-untagged" {
+ value 3;
+ description
+ "The VLAN mode native-untagged.";
+ }
+ enum "trunk" {
+ value 4;
+ description
+ "The VLAN mode trunk.";
+ }
+ enum "trunk-member" {
+ value 5;
+ description
+ "The VLAN mode trunk-member.";
+ }
+ enum "transparent" {
+ value 6;
+ description
+ "The VLAN mode transparent.";
+ }
+ }
+ default "trunk";
+ }
+ }
+
+ /* Q-in-Q logical port */
+ augment "/if:interfaces/if:interface" {
+ ext:augment-identifier "if-stacked-vlan";
+ when "if:type = 'stacked-vlan'";
+ leaf stacked_vlan-id {
+ type uint16 {
+ range "1..4094";
+ }
+ }
+ }
+
+ augment "/if:interfaces/if:interface" {
+ ext:augment-identifier "if-tunnel";
+ when "if:type = 'ianaift:tunnel'";
+
+ leaf internal {
+ type boolean;
+ default "false";
+ description
+ "represents whether this is an internal or external tunnel.";
+ }
+
+ leaf tunnel-interface-type {
+ type identityref {
+ base tunnel-type-base;
+ }
+ }
+
+ leaf tunnel-source {
+ type inet:ip-address;
+ description "Local Endpoint IP address";
+ }
+
+ leaf tunnel-destination {
+ type inet:ip-address;
+ description "Remote Endpoint IP address";
+ }
+
+ leaf tunnel-gateway {
+ type inet:ip-address;
+ description "gateway IP address";
+ }
+
+ leaf monitor-enabled {
+ type boolean;
+ default false;
+ }
+
+ leaf monitor-interval {
+ type uint32;
+ default 10000;
+ }
+ }
+
+ augment "/if:interfaces/if:interface" {
+ status deprecated;
+ ext:augment-identifier "if-l3tunnel";
+ when "if:type = 'ianaift:l3tunnel'";
+
+ leaf tunnel-type {
+ type identityref {
+ base tunnel-type-base;
+ }
+ }
+
+ leaf local-ip {
+ type inet:ip-address;
+ description "Local Endpoint IP address";
+ }
+
+ leaf remote-ip {
+ type inet:ip-address;
+ description "Remote Endpoint IP address";
+ }
+
+ leaf gateway-ip {
+ type inet:ip-address;
+ description "gateway IP address";
+ }
+ }
+
+ /* MPLS logical port */
+ augment "/if:interfaces/if:interface" {
+ ext:augment-identifier "if-mpls";
+ when "if:type = 'mpls'";
+ leaf-list labelStack {
+ type uint32 {
+ range "15..1048575";
+ }
+ }
+ leaf numLabels{
+ type uint8 {
+ range "1..7";
+ }
+ }
+ }
+}
\ 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) 2015 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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>interfacemgr-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>interfacemgr-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.model</groupId>
+ <artifactId>model-flow-service</artifactId>
+ <version>${openflowplugin.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-interfaces</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>mdsalutil-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>idmanager-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>alivenessmonitor-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.ovsdb</groupId>
+ <artifactId>hwvtepsouthbound-api</artifactId>
+ <version>${vpns.ovsdb.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.ovsdb</groupId>
+ <artifactId>southbound-api</artifactId>
+ <version>${vpns.ovsdb.version}</version>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright (c) 2015 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:vpnservice:interfacemgr?module=odl-interface&revision=2015-03-31</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:interfacemgr:impl?module=interfacemgr-impl&revision=2015-03-25</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:mdsalutil:api?module=odl-mdsalutil&revision=2015-04-10</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>
+ </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:interfacemgr:impl">prefix:interfacemgr-impl</type>
+ <name>interfacemgr-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>
+ <mdsalutil>
+ <type xmlns:mdsalutil="urn:opendaylight:params:xml:ns:yang:mdsalutil:api">mdsalutil:odl-mdsalutil</type>
+ <name>mdsalutil-service</name>
+ </mdsalutil>
+ <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>
+ <rpc-registry>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+ <name>binding-rpc-broker</name>
+ </rpc-registry>
+ </module>
+ </modules>
+ <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <service>
+ <type xmlns:prefix="urn:opendaylight:vpnservice:interfacemgr">prefix:odl-interface</type>
+ <instance>
+ <name>interfacemgr-service</name>
+ <provider>/modules/module[type='interfacemgr-impl'][name='interfacemgr-default']</provider>
+ </instance>
+ </service>
+ </services>
+ </data>
+ </configuration>
+</snapshot>
\ No newline at end of file
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.vpnservice.interfacemgr;
+
+import java.math.BigInteger;
+
+public class IfmConstants {
+ 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;
+ public static final String IFM_IDPOOL_SIZE = "65535";
+ 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 DEFAULT_FLOW_PRIORITY = 5;
+ public static final String IFM_LPORT_TAG_IDPOOL_NAME = "vlaninterfaces.lporttag";
+ 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 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);
+ public static final short DEFAULT_SERVICE_INDEX = 0;
+ public static final int FLOW_HIGH_PRIORITY = 10;
+ public static final int FLOW_PRIORITY_FOR_UNTAGGED_VLAN = 4;
+ public static final BigInteger VLAN_TABLE_COOKIE = new BigInteger("8000000", 16);
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.interfacemgr;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import com.google.common.base.Optional;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+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.vpnservice.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.ActionType;
+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.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadata;
+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.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+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.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.AllocateIdOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
+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.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan.L2vlanMode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class IfmUtil {
+ private static final Logger LOG = LoggerFactory.getLogger(IfmUtil.class);
+ private static final int INVALID_ID = 0;
+
+
+
+ public static String getDpnFromNodeConnectorId(NodeConnectorId portId) {
+ /*
+ * NodeConnectorId is of form 'openflow:dpnid:portnum'
+ */
+ String[] split = portId.getValue().split(IfmConstants.OF_URI_SEPARATOR);
+ return split[1];
+ }
+
+ public static BigInteger getDpnFromInterface(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState){
+ NodeConnectorId ncId = getNodeConnectorIdFromInterface(ifState);
+ if(ncId != null){
+ return new BigInteger(getDpnFromNodeConnectorId(ncId));
+ }
+ return null;
+ }
+ public static String getPortNoFromInterfaceName(String ifaceName, DataBroker broker) {
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
+ InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(ifaceName, broker);
+
+ String lowerLayerIf = ifState.getLowerLayerIf().get(0);
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
+ String portNo = IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId);
+
+ return portNo;
+ }
+
+ public static String getPortNoFromNodeConnectorId(NodeConnectorId portId) {
+ /*
+ * NodeConnectorId is of form 'openflow:dpnid:portnum'
+ */
+ String[] split = portId.getValue().split(IfmConstants.OF_URI_SEPARATOR);
+ return split[2];
+ }
+
+ public static NodeId buildDpnNodeId(BigInteger dpnId) {
+ return new NodeId(IfmConstants.OF_URI_PREFIX + dpnId);
+ }
+
+ public static InstanceIdentifier<Interface> buildId(String interfaceName) {
+ //TODO Make this generic and move to AbstractDataChangeListener or Utils.
+ InstanceIdentifierBuilder<Interface> idBuilder =
+ InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName));
+ InstanceIdentifier<Interface> id = idBuilder.build();
+ return id;
+ }
+
+ public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> buildStateInterfaceId(String interfaceName) {
+ InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> idBuilder =
+ InstanceIdentifier.builder(InterfacesState.class)
+ .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class,
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName));
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> id = idBuilder.build();
+ return id;
+ }
+
+ public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey getStateInterfaceKeyFromName(
+ String name) {
+ return new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(name);
+ }
+
+ public static InstanceIdentifier<IdPool> getPoolId(String poolName){
+ InstanceIdentifier.InstanceIdentifierBuilder<IdPool> idBuilder =
+ InstanceIdentifier.builder(IdPools.class).child(IdPool.class, new IdPoolKey(poolName));
+ InstanceIdentifier<IdPool> id = idBuilder.build();
+ return id;
+ }
+
+ public static List<String> getPortNameAndSuffixFromInterfaceName(String intfName) {
+ List<String> strList = new ArrayList<>(2);
+ int index = intfName.indexOf(":");
+ if (index != -1) {
+ strList.add(0, intfName.substring(0, index));
+ strList.add(1, intfName.substring(index));
+ }
+ 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(":");
+ if (index1 != -1) {
+ int index2 = intfName.indexOf(":", index1 + 1 );
+ strList.add(0, intfName.substring(0, index1));
+ if (index2 != -1) {
+ strList.add(1, intfName.substring(index1, index2));
+ strList.add(2, intfName.substring(index2));
+ } else {
+ strList.add(1, intfName.substring(index1));
+ strList.add(2, "");
+ }
+ }
+ return strList;
+ }
+
+ public static <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, DataBroker broker) {
+
+ 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 List<Action> getEgressActionsForInterface(String interfaceName, Long tunnelKey, DataBroker dataBroker) {
+ List<ActionInfo> listActionInfo = getEgressActionInfosForInterface(interfaceName, tunnelKey, 0, dataBroker);
+ List<Action> actionsList = new ArrayList<>();
+ for (ActionInfo actionInfo : listActionInfo) {
+ actionsList.add(actionInfo.buildAction());
+ }
+ return actionsList;
+ }
+
+ public static List<ActionInfo> getEgressActionInfosForInterface(String interfaceName,
+ int actionKeyStart,
+ DataBroker dataBroker) {
+ return getEgressActionInfosForInterface(interfaceName, null, actionKeyStart, dataBroker);
+ }
+
+ /**
+ * Returns a list of Actions to be taken when sending a packet over an interface
+ *
+ * @param interfaceName
+ * @param tunnelKey Optional.
+ * @param actionKeyStart
+ * @param dataBroker
+ * @return
+ */
+ public static List<ActionInfo> getEgressActionInfosForInterface(String interfaceName,
+ Long tunnelKey,
+ int actionKeyStart,
+ DataBroker dataBroker) {
+ List<ActionInfo> result = new ArrayList<ActionInfo>();
+ Interface interfaceInfo = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(interfaceName),
+ dataBroker);
+ String portNo = IfmUtil.getPortNoFromInterfaceName(interfaceName, dataBroker);
+
+ InterfaceInfo.InterfaceType ifaceType = getInterfaceType(interfaceInfo);
+
+ switch (ifaceType ) {
+ case VLAN_INTERFACE:
+ IfL2vlan vlanIface = interfaceInfo.getAugmentation(IfL2vlan.class);
+ LOG.trace("L2Vlan: {}",vlanIface);
+ boolean isVlanTransparent = false;
+ long vlanVid = 0;
+ if (vlanIface != null) {
+ vlanVid = vlanIface.getVlanId() == null ? 0 : vlanIface.getVlanId().getValue();
+ isVlanTransparent = vlanIface.getL2vlanMode() == IfL2vlan.L2vlanMode.Transparent;
+ }
+ if (vlanVid != 0 && !isVlanTransparent) {
+ result.add(new ActionInfo(ActionType.push_vlan, new String[] {}, actionKeyStart));
+ actionKeyStart++;
+ result.add(new ActionInfo(ActionType.set_field_vlan_vid,
+ new String[] { Long.toString(vlanVid) }, actionKeyStart));
+ actionKeyStart++;
+ }
+ result.add(new ActionInfo(ActionType.output, new String[] {portNo}, actionKeyStart));
+ actionKeyStart++;
+ break;
+ case MPLS_OVER_GRE:
+ case VXLAN_TRUNK_INTERFACE:
+ case GRE_TRUNK_INTERFACE:
+ if(tunnelKey != null) {
+ result.add(new ActionInfo(ActionType.set_field_tunnel_id,
+ new BigInteger[] { BigInteger.valueOf(tunnelKey.longValue()) },
+ actionKeyStart) );
+ actionKeyStart++;
+ }
+
+ result.add(new ActionInfo(ActionType.output, new String[] { portNo}, actionKeyStart));
+ actionKeyStart++;
+ break;
+
+ default:
+ LOG.warn("Interface Type {} not handled yet", ifaceType);
+ break;
+ }
+
+ return result;
+ }
+
+
+ public static NodeId getNodeIdFromNodeConnectorId(NodeConnectorId ncId) {
+ return new NodeId(ncId.getValue().substring(0,ncId.getValue().lastIndexOf(":")));
+ }
+
+ public static BigInteger[] mergeOpenflowMetadataWriteInstructions(List<Instruction> instructions) {
+ BigInteger metadata = new BigInteger("0", 16);
+ BigInteger metadataMask = new BigInteger("0", 16);
+ if (instructions != null && !instructions.isEmpty()) {
+ // check if metadata write instruction is present
+ for (Instruction instruction : instructions) {
+ org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction actualInstruction = instruction.getInstruction();
+ if (actualInstruction instanceof WriteMetadataCase) {
+ WriteMetadataCase writeMetaDataInstruction = (WriteMetadataCase) actualInstruction ;
+ WriteMetadata availableMetaData = writeMetaDataInstruction.getWriteMetadata();
+ metadata = metadata.or(availableMetaData.getMetadata());
+ metadataMask = metadataMask.or(availableMetaData.getMetadataMask());
+ }
+ }
+ }
+ return new BigInteger[] { metadata, metadataMask };
+ }
+
+ public static Integer allocateId(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 {
+ LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when getting Unique Id",e);
+ }
+ return INVALID_ID;
+ }
+
+ public static void releaseId(IdManagerService idManager, String poolName, String idKey) {
+ ReleaseIdInput idInput = new ReleaseIdInputBuilder()
+ .setPoolName(poolName)
+ .setIdKey(idKey).build();
+ try {
+ Future<RpcResult<Void>> result = idManager.releaseId(idInput);
+ RpcResult<Void> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to release Id {} with Key {} returned with Errors {}",
+ idKey, rpcResult.getErrors());
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when releasing Id for key {}", idKey, e);
+ }
+ }
+
+ public static BigInteger getDpnId(DatapathId datapathId){
+ if (datapathId != null) {
+ // Adding logs for a random issue spotted during datapath id conversion
+ LOG.info("Received datapathId {}",datapathId.getValue());
+ String dpIdStr = datapathId.getValue().replace(":", "");
+ LOG.info("Received datapathId {}",dpIdStr);
+ BigInteger dpnId = new BigInteger(dpIdStr, 16);
+ LOG.info("After conversion datapathId {}",dpnId);
+ return dpnId;
+ }
+ return null;
+ }
+
+ public static NodeConnectorId getNodeConnectorIdFromInterface(Interface iface, DataBroker dataBroker) {
+ return FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
+ }
+
+ public static String getPortName(DataBroker dataBroker, NodeConnectorId ncId){
+ InstanceIdentifier<NodeConnector> ncIdentifier =
+ InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, new NodeKey(getNodeIdFromNodeConnectorId(ncId)))
+ .child(NodeConnector.class, new NodeConnectorKey(ncId)).build();
+ Optional<NodeConnector> optNc = read(LogicalDatastoreType.OPERATIONAL, ncIdentifier, dataBroker);
+ if(optNc.isPresent()) {
+ NodeConnector nc = optNc.get();
+ FlowCapableNodeConnector fcnc = nc.getAugmentation(FlowCapableNodeConnector.class);
+ return fcnc.getName();
+ }
+ return null;
+ }
+
+ public static NodeConnectorId getNodeConnectorIdFromInterface(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState){
+ if(ifState != null) {
+ List<String> ofportIds = ifState.getLowerLayerIf();
+ return new NodeConnectorId(ofportIds.get(0));
+ }
+ return null;
+ }
+
+ 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;
+ } else if(tunnelType.isAssignableFrom(TunnelTypeMplsOverGre.class)){
+ interfaceType = InterfaceInfo.InterfaceType.MPLS_OVER_GRE;
+ }
+ }
+ // 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;
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.interfacemgr;
+
+
+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.binding.api.WriteTransaction;
+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.AlivenessMonitorListener;
+import org.opendaylight.vpnservice.interfacemgr.listeners.InterfaceConfigListener;
+import org.opendaylight.vpnservice.interfacemgr.listeners.HwVTEPConfigListener;
+import org.opendaylight.vpnservice.interfacemgr.listeners.HwVTEPTunnelsStateListener;
+import org.opendaylight.vpnservice.interfacemgr.listeners.InterfaceInventoryStateListener;
+import org.opendaylight.vpnservice.interfacemgr.listeners.TerminationPointStateListener;
+import org.opendaylight.vpnservice.interfacemgr.listeners.InterfaceTopologyStateListener;
+import org.opendaylight.vpnservice.interfacemgr.listeners.VlanMemberConfigListener;
+import org.opendaylight.vpnservice.interfacemgr.pmcounters.NodeConnectorStatsImpl;
+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.statusanddiag.InterfaceStatusMonitor;
+import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+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.ietf.inet.types.rev100924.IpAddress;
+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.InterfaceBuilder;
+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.AdminStatus;
+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.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+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.service.bindings.ServicesInfo;
+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.BoundServicesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+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.rev150331.IfL2vlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlanBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.*;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+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 static final InterfaceStatusMonitor interfaceStatusMonitor = InterfaceStatusMonitor.getInstance();
+
+ private RpcProviderRegistry rpcProviderRegistry;
+ private IdManagerService idManager;
+ private NotificationService notificationService;
+ private AlivenessMonitorService alivenessManager;
+ private IMdsalApiManager mdsalManager;
+ private InterfaceConfigListener interfaceConfigListener;
+ private InterfaceTopologyStateListener topologyStateListener;
+ private TerminationPointStateListener terminationPointStateListener;
+ private HwVTEPTunnelsStateListener hwVTEPTunnelsStateListener;
+ private InterfaceInventoryStateListener interfaceInventoryStateListener;
+ private FlowBasedServicesInterfaceStateListener flowBasedServicesInterfaceStateListener;
+ private FlowBasedServicesConfigListener flowBasedServicesConfigListener;
+ private VlanMemberConfigListener vlanMemberConfigListener;
+ private HwVTEPConfigListener hwVTEPConfigListener;
+ private AlivenessMonitorListener alivenessMonitorListener;
+ private DataBroker dataBroker;
+ private InterfaceManagerRpcService interfaceManagerRpcService;
+ private BindingAwareBroker.RpcRegistration<OdlInterfaceRpcService> rpcRegistration;
+ private NodeConnectorStatsImpl nodeConnectorStatsManager;
+
+ public void setRpcProviderRegistry(RpcProviderRegistry rpcProviderRegistry) {
+ this.rpcProviderRegistry = rpcProviderRegistry;
+ interfaceStatusMonitor.registerMbean();
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ public void setNotificationService(NotificationService notificationService) {
+ this.notificationService = notificationService;
+ }
+
+ @Override
+ public void onSessionInitiated(ProviderContext session) {
+ LOG.info("InterfacemgrProvider Session Initiated");
+ interfaceStatusMonitor.reportStatus("STARTING");
+ try {
+ dataBroker = session.getSALService(DataBroker.class);
+ idManager = rpcProviderRegistry.getRpcService(IdManagerService.class);
+ createIdPool();
+
+ alivenessManager = rpcProviderRegistry.getRpcService(AlivenessMonitorService.class);
+ interfaceManagerRpcService = new InterfaceManagerRpcService(dataBroker, mdsalManager);
+ rpcRegistration = getRpcProviderRegistry().addRpcImplementation(
+ OdlInterfaceRpcService.class, interfaceManagerRpcService);
+
+ interfaceConfigListener = new InterfaceConfigListener(dataBroker, idManager,alivenessManager, mdsalManager);
+ interfaceConfigListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
+
+ interfaceInventoryStateListener = new InterfaceInventoryStateListener(dataBroker, idManager, mdsalManager, alivenessManager);
+ interfaceInventoryStateListener.registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
+
+ topologyStateListener = new InterfaceTopologyStateListener(dataBroker);
+ topologyStateListener.registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
+
+ hwVTEPTunnelsStateListener = new HwVTEPTunnelsStateListener(dataBroker);
+ hwVTEPTunnelsStateListener.registerListener(LogicalDatastoreType.OPERATIONAL,dataBroker);
+
+ terminationPointStateListener = new TerminationPointStateListener(dataBroker);
+ terminationPointStateListener.registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
+
+ flowBasedServicesConfigListener = new FlowBasedServicesConfigListener(dataBroker);
+ flowBasedServicesConfigListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
+
+ flowBasedServicesInterfaceStateListener =
+ new FlowBasedServicesInterfaceStateListener(dataBroker);
+ flowBasedServicesInterfaceStateListener.registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
+
+ vlanMemberConfigListener =
+ new VlanMemberConfigListener(dataBroker, idManager, alivenessManager,mdsalManager);
+ vlanMemberConfigListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
+
+ hwVTEPConfigListener = new HwVTEPConfigListener(dataBroker);
+ hwVTEPConfigListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
+
+ alivenessMonitorListener = new org.opendaylight.vpnservice.interfacemgr.listeners.AlivenessMonitorListener(dataBroker);
+ notificationService.registerNotificationListener(alivenessMonitorListener);
+
+ //Initialize nodeconnectorstatsimpl
+ nodeConnectorStatsManager = new NodeConnectorStatsImpl(dataBroker, notificationService,
+ session.getRpcService(OpendaylightPortStatisticsService.class), session.getRpcService(OpendaylightFlowTableStatisticsService.class));
+
+
+ interfaceStatusMonitor.reportStatus("OPERATIONAL");
+ } catch (Exception e) {
+ LOG.error("Error initializing services", e);
+ interfaceStatusMonitor.reportStatus("ERROR");
+ }
+ }
+
+ private void createIdPool() {
+ CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
+ .setPoolName(IfmConstants.IFM_IDPOOL_NAME)
+ .setLow(IfmConstants.IFM_ID_POOL_START)
+ .setHigh(IfmConstants.IFM_ID_POOL_END)
+ .build();
+ //TODO: Error handling
+ Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
+ try {
+ if ((result != null) && (result.get().isSuccessful())) {
+ LOG.debug("Created IdPool for InterfaceMgr");
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Failed to create idPool for InterfaceMgr",e);
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ LOG.info("InterfacemgrProvider Closed");
+ interfaceConfigListener.close();
+ rpcRegistration.close();
+ }
+
+ public RpcProviderRegistry getRpcProviderRegistry() {
+ return rpcProviderRegistry;
+ }
+
+ @Override
+ public Long getPortForInterface(String ifName) {
+ GetPortFromInterfaceInput input = new GetPortFromInterfaceInputBuilder().setIntfName(ifName).build();
+ Future<RpcResult<GetPortFromInterfaceOutput>> output = interfaceManagerRpcService.getPortFromInterface(input);
+ try {
+ RpcResult<GetPortFromInterfaceOutput> port = output.get();
+ if(port.isSuccessful()){
+ return port.getResult().getPortno();
+ }
+ }catch(NullPointerException | InterruptedException | ExecutionException e){
+ LOG.warn("Exception when getting port for interface",e);
+ }
+ return null;
+ }
+
+ @Override
+ public Long getPortForInterface(Interface intf) {
+ GetPortFromInterfaceInput input = new GetPortFromInterfaceInputBuilder().setIntfName(intf.getName()).build();
+ Future<RpcResult<GetPortFromInterfaceOutput>> output = interfaceManagerRpcService.getPortFromInterface(input);
+ try {
+ RpcResult<GetPortFromInterfaceOutput> port = output.get();
+ if(port.isSuccessful()){
+ return port.getResult().getPortno();
+ }
+ }catch(NullPointerException | InterruptedException | ExecutionException e){
+ LOG.warn("Exception when getting port for interface",e);
+ }
+ 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);
+ if (intf == null) {
+ LOG.error("Interface {} doesn't exist in config datastore", interfaceName);
+ return null;
+ }
+
+ 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();
+ NodeConnectorId ncId = IfmUtil.getNodeConnectorIdFromInterface(ifState);
+ if (ncId != null) {
+ interfaceInfo.setDpId(new BigInteger(IfmUtil.getDpnFromNodeConnectorId(ncId)));
+ interfaceInfo.setPortNo(Integer.parseInt(IfmUtil.getPortNoFromNodeConnectorId(ncId)));
+ }
+ interfaceInfo.setAdminState((ifState.getAdminStatus() == AdminStatus.Up) ? 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) {
+ 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();
+ InterfaceInfo interfaceInfo = new InterfaceInfo(interfaceName);
+ NodeConnectorId ncId = IfmUtil.getNodeConnectorIdFromInterface(ifState);
+ if (ncId != null) {
+ interfaceInfo.setPortName(IfmUtil.getPortName(dataBroker, ncId));
+ interfaceInfo.setDpId(new BigInteger(IfmUtil.getDpnFromNodeConnectorId(ncId)));
+ interfaceInfo.setPortNo(Integer.parseInt(IfmUtil.getPortNoFromNodeConnectorId(ncId)));
+ }
+ interfaceInfo.setAdminState((ifState.getAdminStatus() == AdminStatus.Up) ? InterfaceAdminState.ENABLED : InterfaceAdminState.DISABLED);
+ interfaceInfo.setInterfaceName(interfaceName);
+ interfaceInfo.setInterfaceTag(lportTag);
+ interfaceInfo.setOpState((ifState.getOperStatus() == OperStatus.Up) ? InterfaceInfo.InterfaceOpState.UP : InterfaceInfo.InterfaceOpState.DOWN);
+ return interfaceInfo;
+ }
+
+ public void createVLANInterface(String interfaceName, String portName, BigInteger dpId, Integer vlanId,
+ String description, IfL2vlan.L2vlanMode l2vlanMode) {
+ LOG.info("Create VLAN interface : {}",interfaceName);
+ InstanceIdentifier<Interface> interfaceInstanceIdentifier = InterfaceManagerCommonUtils.
+ getInterfaceIdentifier(new InterfaceKey(interfaceName));
+ IfL2vlanBuilder l2vlanBuilder = new IfL2vlanBuilder().setL2vlanMode(l2vlanMode);
+ if(vlanId > 0){
+ l2vlanBuilder.setVlanId(new VlanId(vlanId));
+ }
+ ParentRefs parentRefs = new ParentRefsBuilder().setParentInterface(portName).build();
+ Interface inf = new InterfaceBuilder().setEnabled(true).setName(interfaceName).setType(L2vlan.class).
+ addAugmentation(IfL2vlan.class, l2vlanBuilder.build()).addAugmentation(ParentRefs.class, parentRefs).
+ setDescription(description).build();
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ t.put(LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier, inf, true);
+ }
+
+ public void bindService(String interfaceName, BoundServices serviceInfo){
+ LOG.info("Binding Service : {}",interfaceName);
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ InstanceIdentifier<BoundServices> boundServicesInstanceIdentifier = InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class, new ServicesInfoKey(interfaceName))
+ .child(BoundServices.class, new BoundServicesKey(serviceInfo.getServicePriority())).build();
+ // List<BoundServices> services = (List<BoundServices>)serviceInfo.getBoundServices();
+ t.put(LogicalDatastoreType.CONFIGURATION, boundServicesInstanceIdentifier, serviceInfo, true);
+ t.submit();
+ }
+
+ public void unbindService(String interfaceName, BoundServices serviceInfo){
+ LOG.info("Unbinding Service : {}",interfaceName);
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ InstanceIdentifier<BoundServices> boundServicesInstanceIdentifier = InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class, new ServicesInfoKey(interfaceName))
+ .child(BoundServices.class, new BoundServicesKey(serviceInfo.getServicePriority())).build();
+ t.delete(LogicalDatastoreType.CONFIGURATION, boundServicesInstanceIdentifier);
+ t.submit();
+ }
+
+ @Override
+ public BigInteger getDpnForInterface(String ifName) {
+ GetDpidFromInterfaceInput input = new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
+ Future<RpcResult<GetDpidFromInterfaceOutput>> output = interfaceManagerRpcService.getDpidFromInterface(input);
+ try {
+ RpcResult<GetDpidFromInterfaceOutput> dpn = output.get();
+ if(dpn.isSuccessful()){
+ return dpn.getResult().getDpid();
+ }
+ }catch(NullPointerException | InterruptedException | ExecutionException e){
+ LOG.warn("Exception when getting port for interface",e);
+ }
+ return null;
+ }
+
+ @Override
+ public String getEndpointIpForDpn(BigInteger dpnId) {
+ GetEndpointIpForDpnInput input = new GetEndpointIpForDpnInputBuilder().setDpid(dpnId).build();
+ Future<RpcResult<GetEndpointIpForDpnOutput>> output = interfaceManagerRpcService.getEndpointIpForDpn(input);
+ try {
+ RpcResult<GetEndpointIpForDpnOutput> ipForDpnOutputRpcResult = output.get();
+ if(ipForDpnOutputRpcResult.isSuccessful()){
+ List<IpAddress> localIps = ipForDpnOutputRpcResult.getResult().getLocalIps();
+ if(!localIps.isEmpty()) {
+ return localIps.get(0).getIpv4Address().getValue();
+ }
+ }
+ }catch(NullPointerException | InterruptedException | ExecutionException e){
+ LOG.warn("Exception when getting port for interface",e);
+ }
+ return null;
+ }
+
+ @Override
+ public List<ActionInfo> getInterfaceEgressActions(String ifName) {
+ return IfmUtil.getEgressActionInfosForInterface(ifName, 0, dataBroker);
+ }
+
+ @Override
+ public BigInteger getDpnForInterface(Interface intrf) {
+ return getDpnForInterface(intrf.getName());
+ }
+
+ @Override
+ public List<Interface> getVlanInterfaces() {
+ List<Interface> vlanList = new ArrayList<Interface>();
+ InstanceIdentifier<Interfaces> interfacesInstanceIdentifier = InstanceIdentifier.builder(Interfaces.class).build();
+ Optional<Interfaces> interfacesOptional = IfmUtil.read(LogicalDatastoreType.CONFIGURATION, interfacesInstanceIdentifier, dataBroker);
+ if (!interfacesOptional.isPresent()) {
+ return vlanList;
+ }
+ Interfaces interfaces = interfacesOptional.get();
+ List<Interface> interfacesList = interfaces.getInterface();
+ for (Interface iface : interfacesList) {
+ if (IfmUtil.getInterfaceType(iface) == InterfaceInfo.InterfaceType.VLAN_INTERFACE) {
+ vlanList.add(iface);
+ }
+ }
+ return vlanList;
+ }
+
+ @Override
+ public List<Interface> getVxlanInterfaces() {
+ return InterfaceManagerCommonUtils.getAllTunnelInterfaces(dataBroker,
+ InterfaceInfo.InterfaceType.VXLAN_TRUNK_INTERFACE);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.interfacemgr.commons;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+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.vpnservice.alivenessmonitor.rev150629.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.params.SourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profile.create.input.Profile;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profile.create.input.ProfileBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.start.input.ConfigBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorIdBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.monitor.id.map.InterfaceMonitorIdKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.monitor.id._interface.map.MonitorIdInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class AlivenessMonitorUtils {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AlivenessMonitorUtils.class);
+ private static final long FAILURE_THRESHOLD = 4;
+ private static final long MONITORING_INTERVAL = 10000;
+ private static final long MONITORING_WINDOW = 4;
+
+ public static void startLLDPMonitoring(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
+ Interface trunkInterface) {
+ //LLDP monitoring for the trunk interface
+ String trunkInterfaceName = trunkInterface.getName();
+ IfTunnel ifTunnel = trunkInterface.getAugmentation(IfTunnel.class);
+ if(ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class) && ifTunnel.isInternal()) {
+ MonitorStartInput lldpMonitorInput = new MonitorStartInputBuilder().setConfig(new ConfigBuilder()
+ .setSource(new SourceBuilder().setEndpointType(getInterfaceForMonitoring(trunkInterfaceName,
+ ifTunnel.getTunnelSource())).build())
+ .setMode(MonitoringMode.OneOne)
+ .setProfileId(allocateProfile(alivenessMonitorService, FAILURE_THRESHOLD, ifTunnel.getMonitorInterval(), MONITORING_WINDOW,
+ EtherTypes.Lldp)).build()).build();
+ try {
+ Future<RpcResult<MonitorStartOutput>> result = alivenessMonitorService.monitorStart(lldpMonitorInput);
+ RpcResult<MonitorStartOutput> rpcResult = result.get();
+ long monitorId;
+ if (rpcResult.isSuccessful()) {
+ monitorId = rpcResult.getResult().getMonitorId();
+ createOrUpdateInterfaceMonitorIdMap(dataBroker, trunkInterfaceName, monitorId);
+ createOrUpdateMonitorIdInterfaceMap(dataBroker, trunkInterfaceName, monitorId);
+ LOG.trace("Started LLDP monitoring with id {}", monitorId);
+ } else {
+ LOG.warn("RPC Call to start monitoring returned with Errors {}", rpcResult.getErrors());
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when starting monitoring", e);
+ }
+ }
+ }
+
+ public static void stopLLDPMonitoring(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
+ Interface trunkInterface) {
+ IfTunnel ifTunnel = trunkInterface.getAugmentation(IfTunnel.class);
+ if(!(ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)&& ifTunnel.isInternal())){
+ return;
+ }
+ LOG.debug("stop LLDP monitoring for {}", trunkInterface.getName());
+ List<Long> monitorIds = getMonitorIdForInterface(dataBroker, trunkInterface.getName());
+ if (monitorIds == null) {
+ LOG.error("Monitor Id doesn't exist for Interface {}", trunkInterface);
+ return;
+ }
+ for (Long monitorId : monitorIds) {
+ String interfaceName = getInterfaceFromMonitorId(dataBroker, monitorId);
+ if (interfaceName != null) {
+ MonitorStopInput input = new MonitorStopInputBuilder().setMonitorId(monitorId).build();
+ alivenessMonitorService.monitorStop(input);
+ removeMonitorIdInterfaceMap(dataBroker, monitorId);
+ removeMonitorIdFromInterfaceMonitorIdMap(dataBroker, interfaceName, monitorId);
+ return;
+ }
+ }
+ }
+
+ public static String getInterfaceFromMonitorId(DataBroker broker, Long monitorId) {
+ InstanceIdentifier<MonitorIdInterface> id = InstanceIdentifier.builder(MonitorIdInterfaceMap.class).child(MonitorIdInterface.class, new MonitorIdInterfaceKey(monitorId)).build();
+ Optional<MonitorIdInterface> interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
+ if(interfaceMonitorIdMap.isPresent()) {
+ return interfaceMonitorIdMap.get().getInterfaceName();
+ }
+ return null;
+ }
+
+ private static void removeMonitorIdInterfaceMap(DataBroker broker, long monitorId) {
+ InstanceIdentifier<MonitorIdInterface> id = InstanceIdentifier.builder(MonitorIdInterfaceMap.class).child(MonitorIdInterface.class, new MonitorIdInterfaceKey(monitorId)).build();
+ Optional<MonitorIdInterface> monitorIdInterfaceMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
+ if(monitorIdInterfaceMap.isPresent()) {
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id);
+ }
+ }
+
+ private static void removeMonitorIdFromInterfaceMonitorIdMap(DataBroker broker, String infName, long monitorId) {
+ InstanceIdentifier<InterfaceMonitorId> id = InstanceIdentifier.builder(InterfaceMonitorIdMap.class).child(InterfaceMonitorId.class, new InterfaceMonitorIdKey(infName)).build();
+ Optional<InterfaceMonitorId> interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
+ if(interfaceMonitorIdMap.isPresent()) {
+ InterfaceMonitorId interfaceMonitorIdInstance = interfaceMonitorIdMap.get();
+ List<Long> existingMonitorIds = interfaceMonitorIdInstance.getMonitorId();
+ if (existingMonitorIds != null && existingMonitorIds.contains(monitorId)) {
+ existingMonitorIds.remove(monitorId);
+ InterfaceMonitorIdBuilder interfaceMonitorIdBuilder = new InterfaceMonitorIdBuilder();
+ interfaceMonitorIdInstance = interfaceMonitorIdBuilder.setKey(new InterfaceMonitorIdKey(infName)).setMonitorId(existingMonitorIds).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, interfaceMonitorIdInstance);
+ }
+ }
+ }
+
+ private static org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.endpoint.type.Interface getInterfaceForMonitoring(String interfaceName, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress ipAddress) {
+ return new org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.endpoint.
+ endpoint.type.InterfaceBuilder().setInterfaceIp(ipAddress).setInterfaceName(interfaceName).build();
+ }
+
+ public static void handleTunnelMonitorUpdates(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
+ Interface interfaceOld, Interface interfaceNew) {
+ String interfaceName = interfaceNew.getName();
+ IfTunnel ifTunnelNew = interfaceNew.getAugmentation(IfTunnel.class);
+ if(!(ifTunnelNew.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)&&
+ ifTunnelNew.isInternal())){
+ return;
+ }
+ LOG.debug("handling tunnel monitoring updates for interface {}", interfaceName);
+
+ stopLLDPMonitoring(alivenessMonitorService, dataBroker, interfaceOld);
+ if(ifTunnelNew.isMonitorEnabled()) {
+ startLLDPMonitoring(alivenessMonitorService, dataBroker, interfaceNew);
+
+ // Delete old profile from Aliveness Manager
+ IfTunnel ifTunnelOld = interfaceOld.getAugmentation(IfTunnel.class);
+ if(ifTunnelNew.getMonitorInterval() != ifTunnelOld.getMonitorInterval()) {
+ LOG.debug("deleting older monitor profile for interface {}", interfaceName);
+ long profileId = allocateProfile(alivenessMonitorService, FAILURE_THRESHOLD, ifTunnelOld.getMonitorInterval(), MONITORING_WINDOW, EtherTypes.Lldp);
+ MonitorProfileDeleteInput profileDeleteInput = new MonitorProfileDeleteInputBuilder().setProfileId(profileId).build();
+ alivenessMonitorService.monitorProfileDelete(profileDeleteInput);
+ }
+ }
+ }
+
+
+ public static void createOrUpdateInterfaceMonitorIdMap(DataBroker broker, String infName, long monitorId) {
+ InterfaceMonitorId interfaceMonitorIdInstance;
+ List<Long> existingMonitorIds;
+ InterfaceMonitorIdBuilder interfaceMonitorIdBuilder = new InterfaceMonitorIdBuilder();
+ InstanceIdentifier<InterfaceMonitorId> id = InstanceIdentifier.builder(InterfaceMonitorIdMap.class).child(InterfaceMonitorId.class, new InterfaceMonitorIdKey(infName)).build();
+ Optional<InterfaceMonitorId> interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
+ if (interfaceMonitorIdMap.isPresent()) {
+ interfaceMonitorIdInstance = interfaceMonitorIdMap.get();
+ existingMonitorIds = interfaceMonitorIdInstance.getMonitorId();
+ if (existingMonitorIds == null) {
+ existingMonitorIds = new ArrayList<>();
+ }
+ if (!existingMonitorIds.contains(monitorId)) {
+ existingMonitorIds.add(monitorId);
+ interfaceMonitorIdInstance = interfaceMonitorIdBuilder.setKey(new InterfaceMonitorIdKey(infName)).setMonitorId(existingMonitorIds).build();
+ MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, id, interfaceMonitorIdInstance);
+ }
+ } else {
+ existingMonitorIds = new ArrayList<>();
+ existingMonitorIds.add(monitorId);
+ interfaceMonitorIdInstance = interfaceMonitorIdBuilder.setMonitorId(existingMonitorIds).setKey(new InterfaceMonitorIdKey(infName)).setInterfaceName(infName).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, interfaceMonitorIdInstance);
+ }
+ }
+
+ public static void createOrUpdateMonitorIdInterfaceMap(DataBroker broker,String infName, long monitorId) {
+ MonitorIdInterface monitorIdInterfaceInstance;
+ String existinginterfaceName;
+ MonitorIdInterfaceBuilder monitorIdInterfaceBuilder = new MonitorIdInterfaceBuilder();
+ InstanceIdentifier<MonitorIdInterface> id = InstanceIdentifier.builder(MonitorIdInterfaceMap.class).child(MonitorIdInterface.class, new MonitorIdInterfaceKey(monitorId)).build();
+ Optional<MonitorIdInterface> monitorIdInterfaceMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
+ if(monitorIdInterfaceMap.isPresent()) {
+ monitorIdInterfaceInstance = monitorIdInterfaceMap.get();
+ existinginterfaceName = monitorIdInterfaceInstance.getInterfaceName();
+ if(!existinginterfaceName.equals(infName)) {
+ monitorIdInterfaceInstance = monitorIdInterfaceBuilder.setKey(new MonitorIdInterfaceKey(monitorId)).setInterfaceName(infName).build();
+ MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, id, monitorIdInterfaceInstance);
+ }
+ } else {
+ monitorIdInterfaceInstance = monitorIdInterfaceBuilder.setMonitorId(monitorId).setKey(new MonitorIdInterfaceKey(monitorId)).setInterfaceName(infName).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id, monitorIdInterfaceInstance);
+ }
+ }
+
+ public static List<Long> getMonitorIdForInterface(DataBroker broker, String infName) {
+ InstanceIdentifier<InterfaceMonitorId> id = InstanceIdentifier.builder(InterfaceMonitorIdMap.class).child(InterfaceMonitorId.class, new InterfaceMonitorIdKey(infName)).build();
+ Optional<InterfaceMonitorId> interfaceMonitorIdMap = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, broker);
+ if(interfaceMonitorIdMap.isPresent()) {
+ return interfaceMonitorIdMap.get().getMonitorId();
+ }
+ return null;
+ }
+
+ public static long createMonitorProfile(AlivenessMonitorService alivenessMonitor, MonitorProfileCreateInput monitorProfileCreateInput) {
+ try {
+ Future<RpcResult<MonitorProfileCreateOutput>> result = alivenessMonitor.monitorProfileCreate(monitorProfileCreateInput);
+ RpcResult<MonitorProfileCreateOutput> rpcResult = result.get();
+ if(rpcResult.isSuccessful()) {
+ return rpcResult.getResult().getProfileId();
+ } else {
+ LOG.warn("RPC Call to Get Profile Id Id returned with Errors {}.. Trying to fetch existing profile ID", rpcResult.getErrors());
+ try{
+ Profile createProfile = monitorProfileCreateInput.getProfile();
+ Future<RpcResult<MonitorProfileGetOutput>> existingProfile = alivenessMonitor.monitorProfileGet(buildMonitorGetProfile(createProfile.getMonitorInterval(), createProfile.getMonitorWindow(), createProfile.getFailureThreshold(), createProfile.getProtocolType()));
+ RpcResult<MonitorProfileGetOutput> rpcGetResult = existingProfile.get();
+ if(rpcGetResult.isSuccessful()){
+ return rpcGetResult.getResult().getProfileId();
+ }else{
+ LOG.warn("RPC Call to Get Existing Profile Id returned with Errors {}", rpcGetResult.getErrors());
+ }
+ }catch(Exception e){
+ LOG.warn("Exception when getting existing profile",e);
+ }
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when allocating profile Id",e);
+ }
+ return 0;
+ }
+
+ private static MonitorProfileGetInput buildMonitorGetProfile(long monitorInterval, long monitorWindow, long failureThreshold, EtherTypes protocolType){
+ MonitorProfileGetInputBuilder buildGetProfile = new MonitorProfileGetInputBuilder();
+ org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profile.get.input.ProfileBuilder profileBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profile.get.input.ProfileBuilder();
+ profileBuilder.setFailureThreshold(failureThreshold);
+ profileBuilder.setMonitorInterval(monitorInterval);
+ profileBuilder.setMonitorWindow(monitorWindow);
+ profileBuilder.setProtocolType(protocolType);
+ buildGetProfile.setProfile(profileBuilder.build());
+ return (buildGetProfile.build());
+ };
+
+ public static long allocateProfile(AlivenessMonitorService alivenessMonitor, long FAILURE_THRESHOLD, long MONITORING_INTERVAL,
+ long MONITORING_WINDOW, EtherTypes etherTypes) {
+ MonitorProfileCreateInput input = new MonitorProfileCreateInputBuilder().
+ setProfile(new ProfileBuilder().setFailureThreshold(FAILURE_THRESHOLD)
+ .setMonitorInterval(MONITORING_INTERVAL).setMonitorWindow(MONITORING_WINDOW).
+ setProtocolType(etherTypes).build()).build();
+ return createMonitorProfile(alivenessMonitor, input);
+ }
+
+ public static long allocateDefaultProfile(AlivenessMonitorService alivenessMonitor, EtherTypes etherType ) {
+ MonitorProfileCreateInput input = new MonitorProfileCreateInputBuilder().
+ setProfile(getDefaultMonitorProfile(etherType)).build();
+ return createMonitorProfile(alivenessMonitor, input);
+ }
+
+ public static Profile getDefaultMonitorProfile(EtherTypes etherType) {
+ ProfileBuilder profileBuilder = new ProfileBuilder();
+ profileBuilder.setProtocolType(etherType);
+ profileBuilder.setFailureThreshold(FAILURE_THRESHOLD)
+ .setMonitorInterval(MONITORING_INTERVAL).setMonitorWindow(MONITORING_WINDOW).setProtocolType(etherType);
+ return profileBuilder.build();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.vpnservice.interfacemgr.commons;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
+import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
+import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
+import org.opendaylight.vpnservice.mdsalutil.InstructionType;
+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.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType;
+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.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
+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.inventory.rev130819.FlowCapableNodeConnector;
+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.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+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.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeMplsOverGre;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class InterfaceManagerCommonUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(InterfaceManagerCommonUtils.class);
+ public static NodeConnector getNodeConnectorFromInventoryOperDS(NodeConnectorId nodeConnectorId,
+ DataBroker dataBroker) {
+ NodeId nodeId = IfmUtil.getNodeIdFromNodeConnectorId(nodeConnectorId);
+ InstanceIdentifier<NodeConnector> ncIdentifier = InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, new NodeKey(nodeId))
+ .child(NodeConnector.class, new NodeConnectorKey(nodeConnectorId)).build();
+
+ Optional<NodeConnector> nodeConnectorOptional = IfmUtil.read(LogicalDatastoreType.OPERATIONAL,
+ ncIdentifier, dataBroker);
+ if (!nodeConnectorOptional.isPresent()) {
+ return null;
+ }
+ return nodeConnectorOptional.get();
+ }
+
+ public static InstanceIdentifier<Interface> getInterfaceIdentifier(InterfaceKey interfaceKey) {
+ InstanceIdentifier.InstanceIdentifierBuilder<Interface> interfaceInstanceIdentifierBuilder =
+ InstanceIdentifier.builder(Interfaces.class).child(Interface.class, interfaceKey);
+ return interfaceInstanceIdentifierBuilder.build();
+ }
+
+ public static List<Interface> getAllTunnelInterfaces(DataBroker dataBroker, InterfaceInfo.InterfaceType interfaceType) {
+ List<Interface> vxlanList = new ArrayList<Interface>();
+ InstanceIdentifier<Interfaces> interfacesInstanceIdentifier = InstanceIdentifier.builder(Interfaces.class).build();
+ Optional<Interfaces> interfacesOptional = IfmUtil.read(LogicalDatastoreType.CONFIGURATION, interfacesInstanceIdentifier, dataBroker);
+ if (!interfacesOptional.isPresent()) {
+ return vxlanList;
+ }
+ Interfaces interfaces = interfacesOptional.get();
+ List<Interface> interfacesList = interfaces.getInterface();
+ for (Interface iface : interfacesList) {
+ if(IfmUtil.getInterfaceType(iface) == InterfaceInfo.InterfaceType.VXLAN_TRUNK_INTERFACE &&
+ iface.getAugmentation(IfTunnel.class).isInternal()) {
+ vxlanList.add(iface);
+ }
+ }
+ return vxlanList;
+ }
+
+ public static Interface getInterfaceFromConfigDS(String interfaceName, DataBroker dataBroker) {
+ InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
+ return getInterfaceFromConfigDS(interfaceKey, dataBroker);
+ }
+
+ public static Interface getInterfaceFromConfigDS(InterfaceKey interfaceKey, DataBroker dataBroker) {
+ InstanceIdentifier<Interface> interfaceId = getInterfaceIdentifier(interfaceKey);
+ Optional<Interface> interfaceOptional = IfmUtil.read(LogicalDatastoreType.CONFIGURATION, interfaceId, dataBroker);
+ if (!interfaceOptional.isPresent()) {
+ return null;
+ }
+
+ return interfaceOptional.get();
+ }
+
+ public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceStateFromOperDS(String interfaceName, DataBroker dataBroker) {
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
+ IfmUtil.buildStateInterfaceId(interfaceName);
+ return getInterfaceStateFromOperDS(ifStateId, dataBroker);
+ }
+
+ public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceStateFromOperDS
+ (InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId, DataBroker dataBroker) {
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateOptional =
+ IfmUtil.read(LogicalDatastoreType.OPERATIONAL, ifStateId, dataBroker);
+ if (!ifStateOptional.isPresent()) {
+ return null;
+ }
+
+ return ifStateOptional.get();
+ }
+ public static void makeTunnelIngressFlow(List<ListenableFuture<Void>> futures, IMdsalApiManager mdsalApiManager,
+ IfTunnel tunnel, BigInteger dpnId, long portNo, Interface iface, int ifIndex, int addOrRemoveFlow) {
+ LOG.debug("make tunnel ingress flow for {}",iface.getName());
+ String flowRef = InterfaceManagerCommonUtils.getTunnelInterfaceFlowRef(dpnId, NwConstants.VLAN_INTERFACE_INGRESS_TABLE, iface.getName());
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
+ if (NwConstants.ADD_FLOW == addOrRemoveFlow) {
+ matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {
+ dpnId, BigInteger.valueOf(portNo) }));
+ mkInstructions.add(new InstructionInfo(
+ InstructionType.write_metadata, new BigInteger[] {
+ MetaDataUtil.getLportTagMetaData(ifIndex).or(BigInteger.ONE),
+ MetaDataUtil.METADATA_MASK_LPORT_TAG_SH_FLAG}));
+ short tableId = tunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeMplsOverGre.class) ? NwConstants.L3_LFIB_TABLE :
+ tunnel.isInternal() ? NwConstants.INTERNAL_TUNNEL_TABLE : NwConstants.DHCP_TABLE_EXTERNAL_TUNNEL;
+ mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] {tableId}));
+ }
+
+ BigInteger COOKIE_VM_INGRESS_TABLE = new BigInteger("8000001", 16);
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, NwConstants.VLAN_INTERFACE_INGRESS_TABLE, flowRef,
+ IfmConstants.DEFAULT_FLOW_PRIORITY, iface.getName(), 0, 0, COOKIE_VM_INGRESS_TABLE, matches, mkInstructions);
+ if (NwConstants.ADD_FLOW == addOrRemoveFlow) {
+ futures.add(mdsalApiManager.installFlow(dpnId, flowEntity));
+ } else {
+ futures.add(mdsalApiManager.removeFlow(dpnId, flowEntity));
+ }
+ }
+ public static String getTunnelInterfaceFlowRef(BigInteger dpnId, short tableId, String ifName) {
+ return new StringBuilder().append(dpnId).append(tableId).append(ifName).toString();
+ }
+
+ public static void setOpStateForInterface(DataBroker broker, String interfaceName, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus opStatus) {
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceId = IfmUtil.buildStateInterfaceId(interfaceName);
+ InterfaceBuilder ifaceBuilder = new InterfaceBuilder().setKey(new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName));
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceData = ifaceBuilder.setOperStatus(opStatus).build();
+ MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceData);
+ }
+
+ public static void createInterfaceChildEntry( WriteTransaction t,
+ String parentInterface, String childInterface){
+ InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(parentInterface);
+ InterfaceChildEntryKey interfaceChildEntryKey = new InterfaceChildEntryKey(childInterface);
+ InstanceIdentifier<InterfaceChildEntry> intfId =
+ InterfaceMetaUtils.getInterfaceChildEntryIdentifier(interfaceParentEntryKey, interfaceChildEntryKey);
+ InterfaceChildEntryBuilder entryBuilder = new InterfaceChildEntryBuilder().setKey(interfaceChildEntryKey)
+ .setChildInterface(childInterface);
+ t.put(LogicalDatastoreType.CONFIGURATION, intfId, entryBuilder.build(),true);
+ }
+
+ public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus
+ updateStateEntry(Interface interfaceNew, DataBroker dataBroker, WriteTransaction transaction,
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus;
+ if (!interfaceNew.isEnabled()) {
+ operStatus = org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
+ } else {
+ String ncStr = ifState.getLowerLayerIf().get(0);
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(ncStr);
+ NodeConnector nodeConnector =
+ InterfaceManagerCommonUtils.getNodeConnectorFromInventoryOperDS(nodeConnectorId, dataBroker);
+ FlowCapableNodeConnector flowCapableNodeConnector =
+ nodeConnector.getAugmentation(FlowCapableNodeConnector.class);
+ //State state = flowCapableNodeConnector.getState();
+ operStatus = flowCapableNodeConnector == null ? org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down : org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Up;
+ }
+
+ String ifName = interfaceNew.getName();
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
+ IfmUtil.buildStateInterfaceId(interfaceNew.getName());
+ InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
+ ifaceBuilder.setOperStatus(operStatus);
+ ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(ifName));
+ transaction.merge(LogicalDatastoreType.OPERATIONAL, ifStateId, ifaceBuilder.build());
+ return operStatus;
+ }
+
+ public static void updateOperStatus(String interfaceName, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus,
+ WriteTransaction transaction) {
+ LOG.debug("updating operational status for interface {}",interfaceName);
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifChildStateId =
+ IfmUtil.buildStateInterfaceId(interfaceName);
+ InterfaceBuilder ifaceBuilderChild = new InterfaceBuilder();
+ ifaceBuilderChild.setOperStatus(operStatus);
+ ifaceBuilderChild.setKey(IfmUtil.getStateInterfaceKeyFromName(interfaceName));
+ transaction.merge(LogicalDatastoreType.OPERATIONAL, ifChildStateId, ifaceBuilderChild.build());
+ }
+
+ public static void addStateEntry(String interfaceName, WriteTransaction transaction, DataBroker dataBroker, IdManagerService idManager,
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
+ LOG.debug("adding interface state for {}",interfaceName);
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus = ifState.getOperStatus();
+ PhysAddress physAddress = ifState.getPhysAddress();
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus adminStatus = ifState.getAdminStatus();
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(ifState.getLowerLayerIf().get(0));
+ InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface interfaceInfo =
+ InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+
+ if (interfaceInfo != null && !interfaceInfo.isEnabled()) {
+ operStatus = org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
+ }
+
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
+ IfmUtil.buildStateInterfaceId(interfaceName);
+ List<String> childLowerLayerIfList = new ArrayList<>();
+ childLowerLayerIfList.add(0, nodeConnectorId.getValue());
+ InterfaceBuilder ifaceBuilder = new InterfaceBuilder().setAdminStatus(adminStatus)
+ .setOperStatus(operStatus).setPhysAddress(physAddress).setLowerLayerIf(childLowerLayerIfList);
+
+ Integer ifIndex = IfmUtil.allocateId(idManager, IfmConstants.IFM_IDPOOL_NAME, interfaceName);
+ ifaceBuilder.setIfIndex(ifIndex);
+
+ if(interfaceInfo != null){
+ ifaceBuilder.setType(interfaceInfo.getType());
+ }
+ ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(interfaceName));
+ transaction.put(LogicalDatastoreType.OPERATIONAL, ifStateId, ifaceBuilder.build(), true);
+
+ // create lportTag Interface Map
+ InterfaceMetaUtils.createLportTagInterfaceMap(transaction, interfaceName, ifIndex);
+
+ // install ingress flow
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
+ if(interfaceInfo != null && interfaceInfo.isEnabled() && ifState.getOperStatus() == org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Up) {
+ List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, interfaceInfo);
+ FlowBasedServicesUtils.installVlanFlow(dpId, portNo, interfaceInfo, transaction, matches, ifIndex);
+ }
+ }
+
+ public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
+ addStateEntry(Interface interfaceInfo, String portName, WriteTransaction transaction, IdManagerService idManager,
+ PhysAddress physAddress, org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus,
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus adminStatus,
+ NodeConnectorId nodeConnectorId) {
+ LOG.debug("adding interface state for {}",portName);
+ if (interfaceInfo != null && !interfaceInfo.isEnabled()) {
+ operStatus = org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
+ }
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
+ IfmUtil.buildStateInterfaceId(portName);
+ List<String> childLowerLayerIfList = new ArrayList<>();
+ childLowerLayerIfList.add(0, nodeConnectorId.getValue());
+ InterfaceBuilder ifaceBuilder = new InterfaceBuilder().setAdminStatus(adminStatus)
+ .setOperStatus(operStatus).setPhysAddress(physAddress).setLowerLayerIf(childLowerLayerIfList);
+
+ Integer ifIndex = IfmUtil.allocateId(idManager, IfmConstants.IFM_IDPOOL_NAME, portName);
+ ifaceBuilder.setIfIndex(ifIndex);
+
+ if(interfaceInfo != null){
+ ifaceBuilder.setType(interfaceInfo.getType());
+ }
+ ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(portName));
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState = ifaceBuilder.build();
+ transaction.put(LogicalDatastoreType.OPERATIONAL, ifStateId,ifState , true);
+
+ // allocate lport tag and set in if-index
+ InterfaceMetaUtils.createLportTagInterfaceMap(transaction, portName, ifIndex);
+ return ifState;
+ }
+
+ public static void deleteStateEntry(String interfaceName, WriteTransaction transaction) {
+ LOG.debug("removing interface state for {}",interfaceName);
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifChildStateId =
+ IfmUtil.buildStateInterfaceId(interfaceName);
+ transaction.delete(LogicalDatastoreType.OPERATIONAL, ifChildStateId);
+ }
+
+ // For trunk interfaces, binding to a parent interface which is already bound to another trunk interface should not
+ // be allowed
+ public static boolean createInterfaceChildEntryIfNotPresent( DataBroker dataBroker, WriteTransaction t,
+ String parentInterface, String childInterface){
+ InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(parentInterface);
+ InstanceIdentifier<InterfaceParentEntry> interfaceParentEntryIdentifier =
+ InterfaceMetaUtils.getInterfaceParentEntryIdentifier(interfaceParentEntryKey);
+ InterfaceParentEntry interfaceParentEntry =
+ InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceParentEntryIdentifier, dataBroker);
+
+ if(interfaceParentEntry != null){
+ LOG.error("Trying to bind the same parent interface {} to multiple trunk interfaces. ", parentInterface);
+ return false;
+ }
+
+ LOG.info("First vlan trunk {} bound on parent-interface {}", childInterface, parentInterface);
+ InterfaceChildEntryKey interfaceChildEntryKey = new InterfaceChildEntryKey(childInterface);
+ InstanceIdentifier<InterfaceChildEntry> intfId =
+ InterfaceMetaUtils.getInterfaceChildEntryIdentifier(interfaceParentEntryKey, interfaceChildEntryKey);
+ InterfaceChildEntryBuilder entryBuilder = new InterfaceChildEntryBuilder().setKey(interfaceChildEntryKey)
+ .setChildInterface(childInterface);
+ t.put(LogicalDatastoreType.CONFIGURATION, intfId, entryBuilder.build(),true);
+ return true;
+ }
+
+ public static boolean deleteParentInterfaceEntry( WriteTransaction t, String parentInterface){
+ InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(parentInterface);
+ InstanceIdentifier<InterfaceParentEntry> interfaceParentEntryIdentifier = InterfaceMetaUtils.getInterfaceParentEntryIdentifier(interfaceParentEntryKey);
+ t.delete(LogicalDatastoreType.CONFIGURATION, interfaceParentEntryIdentifier);
+ return true;
+ }
+
+ public static void deleteInterfaceChildEntry(WriteTransaction transaction, DataBroker dataBroker, String parentInterface, String childInterface){
+ InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(parentInterface);
+ InstanceIdentifier<InterfaceParentEntry> interfaceParentEntryIid =
+ InterfaceMetaUtils.getInterfaceParentEntryIdentifier(interfaceParentEntryKey);
+ InterfaceParentEntry interfaceParentEntry =
+ InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceParentEntryIid, dataBroker);
+
+ if(interfaceParentEntry == null){
+ return;
+ }
+
+ List<InterfaceChildEntry> interfaceChildEntries = interfaceParentEntry.getInterfaceChildEntry();
+ if (interfaceChildEntries.size() <= 1) {
+ transaction.delete(LogicalDatastoreType.CONFIGURATION, interfaceParentEntryIid);
+ } else {
+ InterfaceChildEntryKey interfaceChildEntryKey = new InterfaceChildEntryKey(childInterface);
+ InstanceIdentifier<InterfaceChildEntry> interfaceChildEntryIid =
+ InterfaceMetaUtils.getInterfaceChildEntryIdentifier(interfaceParentEntryKey, interfaceChildEntryKey);
+ transaction.delete(LogicalDatastoreType.CONFIGURATION, interfaceChildEntryIid);
+ }
+ }
+
+ /*
+ * update operational state of interface based on events like tunnel monitoring
+ */
+ public static void updateOpState(WriteTransaction transaction, String interfaceName,
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus){
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
+ IfmUtil.buildStateInterfaceId(interfaceName);
+ LOG.debug("updating tep interface state as {} for {}", operStatus.name(), interfaceName);
+ InterfaceBuilder ifaceBuilder = new InterfaceBuilder().setOperStatus(operStatus);
+ ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(interfaceName));
+ transaction.merge(LogicalDatastoreType.OPERATIONAL, ifStateId, ifaceBuilder.build());
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.interfacemgr.commons;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+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.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.Tunnels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.*;
+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.IfIndexInterfaceBuilder;
+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.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.tunnel.instance._interface.map.TunnelInstanceInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.tunnel.instance._interface.map.TunnelInstanceInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.tunnel.instance._interface.map.TunnelInstanceInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+
+public class InterfaceMetaUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(InterfaceMetaUtils.class);
+ public static InstanceIdentifier<BridgeRefEntry> getBridgeRefEntryIdentifier(BridgeRefEntryKey bridgeRefEntryKey) {
+ InstanceIdentifier.InstanceIdentifierBuilder<BridgeRefEntry> bridgeRefEntryInstanceIdentifierBuilder =
+ InstanceIdentifier.builder(BridgeRefInfo.class)
+ .child(BridgeRefEntry.class, bridgeRefEntryKey);
+ return bridgeRefEntryInstanceIdentifierBuilder.build();
+ }
+
+ public static BridgeRefEntry getBridgeRefEntryFromOperDS(InstanceIdentifier<BridgeRefEntry> dpnBridgeEntryIid,
+ DataBroker dataBroker) {
+ Optional<BridgeRefEntry> bridgeRefEntryOptional =
+ IfmUtil.read(LogicalDatastoreType.OPERATIONAL, dpnBridgeEntryIid, dataBroker);
+ if (!bridgeRefEntryOptional.isPresent()) {
+ return null;
+ }
+ return bridgeRefEntryOptional.get();
+ }
+
+ public static BridgeRefEntry getBridgeReferenceForInterface(Interface interfaceInfo,
+ DataBroker dataBroker) {
+ ParentRefs parentRefs = interfaceInfo.getAugmentation(ParentRefs.class);
+ BigInteger dpn = parentRefs.getDatapathNodeIdentifier();
+ BridgeRefEntryKey BridgeRefEntryKey = new BridgeRefEntryKey(dpn);
+ InstanceIdentifier<BridgeRefEntry> dpnBridgeEntryIid = getBridgeRefEntryIdentifier(BridgeRefEntryKey);
+ BridgeRefEntry bridgeRefEntry = getBridgeRefEntryFromOperDS(dpnBridgeEntryIid, dataBroker);
+ return bridgeRefEntry;
+ }
+
+ public static boolean bridgeExists(BridgeRefEntry bridgeRefEntry,
+ DataBroker dataBroker) {
+ if (bridgeRefEntry != null && bridgeRefEntry.getBridgeReference() != null) {
+ InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid =
+ (InstanceIdentifier<OvsdbBridgeAugmentation>) bridgeRefEntry.getBridgeReference().getValue();
+ Optional<OvsdbBridgeAugmentation> bridgeNodeOptional =
+ IfmUtil.read(LogicalDatastoreType.OPERATIONAL, bridgeIid, dataBroker);
+ if (bridgeNodeOptional.isPresent()) {
+ return true;
+ }
+ }
+ return false;
+ }
+ public static InstanceIdentifier<BridgeEntry> getBridgeEntryIdentifier(BridgeEntryKey bridgeEntryKey) {
+ InstanceIdentifier.InstanceIdentifierBuilder<BridgeEntry> bridgeEntryIdBuilder =
+ InstanceIdentifier.builder(BridgeInterfaceInfo.class).child(BridgeEntry.class, bridgeEntryKey);
+ return bridgeEntryIdBuilder.build();
+ }
+
+ public static BridgeEntry getBridgeEntryFromConfigDS(BigInteger dpnId,
+ DataBroker dataBroker) {
+ BridgeEntryKey bridgeEntryKey = new BridgeEntryKey(dpnId);
+ InstanceIdentifier<BridgeEntry> bridgeEntryInstanceIdentifier =
+ InterfaceMetaUtils.getBridgeEntryIdentifier(bridgeEntryKey);
+ LOG.debug("Trying to retrieve bridge entry from config for Id: {}", bridgeEntryInstanceIdentifier);
+ return getBridgeEntryFromConfigDS(bridgeEntryInstanceIdentifier,
+ dataBroker);
+ }
+
+ public static BridgeEntry getBridgeEntryFromConfigDS(InstanceIdentifier<BridgeEntry> bridgeEntryInstanceIdentifier,
+ DataBroker dataBroker) {
+ Optional<BridgeEntry> bridgeEntryOptional =
+ IfmUtil.read(LogicalDatastoreType.CONFIGURATION, bridgeEntryInstanceIdentifier, dataBroker);
+ if (!bridgeEntryOptional.isPresent()) {
+ return null;
+ }
+ return bridgeEntryOptional.get();
+ }
+
+ public static InstanceIdentifier<BridgeInterfaceEntry> getBridgeInterfaceEntryIdentifier(BridgeEntryKey bridgeEntryKey,
+ BridgeInterfaceEntryKey bridgeInterfaceEntryKey) {
+ return InstanceIdentifier.builder(BridgeInterfaceInfo.class)
+ .child(BridgeEntry.class, bridgeEntryKey)
+ .child(BridgeInterfaceEntry.class, bridgeInterfaceEntryKey).build();
+
+ }
+
+ public static void createBridgeInterfaceEntryInConfigDS(BridgeEntryKey bridgeEntryKey,
+ BridgeInterfaceEntryKey bridgeInterfaceEntryKey,
+ String childInterface,
+ WriteTransaction t) {
+ InstanceIdentifier<BridgeInterfaceEntry> bridgeInterfaceEntryIid =
+ InterfaceMetaUtils.getBridgeInterfaceEntryIdentifier(bridgeEntryKey, bridgeInterfaceEntryKey);
+ BridgeInterfaceEntryBuilder entryBuilder = new BridgeInterfaceEntryBuilder().setKey(bridgeInterfaceEntryKey)
+ .setInterfaceName(childInterface);
+ t.put(LogicalDatastoreType.CONFIGURATION, bridgeInterfaceEntryIid, entryBuilder.build(), true);
+ }
+
+ public static InstanceIdentifier<InterfaceParentEntry> getInterfaceParentEntryIdentifier(
+ InterfaceParentEntryKey interfaceParentEntryKey) {
+ InstanceIdentifier.InstanceIdentifierBuilder<InterfaceParentEntry> intfIdBuilder =
+ InstanceIdentifier.builder(InterfaceChildInfo.class)
+ .child(InterfaceParentEntry.class, interfaceParentEntryKey);
+ return intfIdBuilder.build();
+ }
+
+ public static InstanceIdentifier<InterfaceChildEntry> getInterfaceChildEntryIdentifier(
+ InterfaceParentEntryKey interfaceParentEntryKey, InterfaceChildEntryKey interfaceChildEntryKey) {
+ InstanceIdentifier.InstanceIdentifierBuilder<InterfaceChildEntry> intfIdBuilder =
+ InstanceIdentifier.builder(InterfaceChildInfo.class)
+ .child(InterfaceParentEntry.class, interfaceParentEntryKey)
+ .child(InterfaceChildEntry.class, interfaceChildEntryKey);
+ return intfIdBuilder.build();
+ }
+
+ public static InterfaceParentEntry getInterfaceParentEntryFromConfigDS(
+ String interfaceName, DataBroker dataBroker) {
+ InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(interfaceName);
+ InterfaceParentEntry interfaceParentEntry =
+ InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceParentEntryKey, dataBroker);
+ return interfaceParentEntry;
+ }
+
+ public static InterfaceParentEntry getInterfaceParentEntryFromConfigDS(
+ InterfaceParentEntryKey interfaceParentEntryKey, DataBroker dataBroker) {
+ InstanceIdentifier<InterfaceParentEntry> intfParentIid =
+ getInterfaceParentEntryIdentifier(interfaceParentEntryKey);
+
+ return getInterfaceParentEntryFromConfigDS(intfParentIid, dataBroker);
+ }
+
+ public static InterfaceParentEntry getInterfaceParentEntryFromConfigDS(
+ InstanceIdentifier<InterfaceParentEntry> intfId, DataBroker dataBroker) {
+ Optional<InterfaceParentEntry> interfaceParentEntryOptional =
+ IfmUtil.read(LogicalDatastoreType.CONFIGURATION, intfId, dataBroker);
+ if (!interfaceParentEntryOptional.isPresent()) {
+ return null;
+ }
+ return interfaceParentEntryOptional.get();
+ }
+
+ public static InterfaceChildEntry getInterfaceChildEntryFromConfigDS(InterfaceParentEntryKey interfaceParentEntryKey,
+ InterfaceChildEntryKey interfaceChildEntryKey,
+ DataBroker dataBroker) {
+ InstanceIdentifier<InterfaceChildEntry> intfChildIid =
+ getInterfaceChildEntryIdentifier(interfaceParentEntryKey, interfaceChildEntryKey);
+
+ return getInterfaceChildEntryFromConfigDS(intfChildIid, dataBroker);
+ }
+
+ public static InterfaceChildEntry getInterfaceChildEntryFromConfigDS(
+ InstanceIdentifier<InterfaceChildEntry> intfChildIid, DataBroker dataBroker) {
+ Optional<InterfaceChildEntry> interfaceChildEntryOptional =
+ IfmUtil.read(LogicalDatastoreType.CONFIGURATION, intfChildIid, dataBroker);
+ if (!interfaceChildEntryOptional.isPresent()) {
+ return null;
+ }
+ return interfaceChildEntryOptional.get();
+ }
+
+ public static void createLportTagInterfaceMap(WriteTransaction t, String infName, Integer ifIndex) {
+ LOG.debug("creating lport tag to interface map for {}",infName);
+ InstanceIdentifier<IfIndexInterface> id = InstanceIdentifier.builder(IfIndexesInterfaceMap.class).child(IfIndexInterface.class, new IfIndexInterfaceKey(ifIndex)).build();
+ IfIndexInterface ifIndexInterface = new IfIndexInterfaceBuilder().setIfIndex(ifIndex).setKey(new IfIndexInterfaceKey(ifIndex)).setInterfaceName(infName).build();
+ t.put(LogicalDatastoreType.OPERATIONAL, id, ifIndexInterface, true);
+ }
+
+ public static void createBridgeRefEntry(BigInteger dpnId, InstanceIdentifier<?> bridgeIid,
+ WriteTransaction tx){
+ LOG.debug("Creating bridge ref entry for dpn: {} bridge: {}",
+ dpnId, bridgeIid);
+ BridgeRefEntryKey bridgeRefEntryKey = new BridgeRefEntryKey(dpnId);
+ InstanceIdentifier<BridgeRefEntry> bridgeEntryId =
+ InterfaceMetaUtils.getBridgeRefEntryIdentifier(bridgeRefEntryKey);
+ BridgeRefEntryBuilder tunnelDpnBridgeEntryBuilder =
+ new BridgeRefEntryBuilder().setKey(bridgeRefEntryKey).setDpid(dpnId)
+ .setBridgeReference(new OvsdbBridgeRef(bridgeIid));
+ tx.put(LogicalDatastoreType.OPERATIONAL, bridgeEntryId, tunnelDpnBridgeEntryBuilder.build(), true);
+ }
+ public static void deleteBridgeRefEntry(BigInteger dpnId,
+ WriteTransaction tx) {
+ LOG.debug("Deleting bridge ref entry for dpn: {}",
+ dpnId);
+ BridgeRefEntryKey bridgeRefEntryKey = new BridgeRefEntryKey(dpnId);
+ InstanceIdentifier<BridgeRefEntry> bridgeEntryId =
+ InterfaceMetaUtils.getBridgeRefEntryIdentifier(bridgeRefEntryKey);
+ tx.delete(LogicalDatastoreType.OPERATIONAL, bridgeEntryId);
+ }
+
+ public static void createTunnelToInterfaceMap(String tunnelInstanceId,
+ String infName,
+ WriteTransaction transaction) {
+ LOG.debug("creating tunnel instance identifier to interface map for {}",infName);
+ InstanceIdentifier<TunnelInstanceInterface> id = InstanceIdentifier.builder(TunnelInstanceInterfaceMap.class).
+ child(TunnelInstanceInterface.class, new TunnelInstanceInterfaceKey(tunnelInstanceId)).build();
+ TunnelInstanceInterface tunnelInstanceInterface = new TunnelInstanceInterfaceBuilder().
+ setTunnelInstanceIdentifier(tunnelInstanceId).setKey(new TunnelInstanceInterfaceKey(tunnelInstanceId)).setInterfaceName(infName).build();
+ transaction.put(LogicalDatastoreType.OPERATIONAL, id, tunnelInstanceInterface, true);
+
+ }
+
+ public static void createTunnelToInterfaceMap(String infName,InstanceIdentifier<Node> nodeId,
+ WriteTransaction transaction,
+ IfTunnel ifTunnel){
+ InstanceIdentifier<Tunnels> tunnelsInstanceIdentifier = org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.utilities.SouthboundUtils.
+ createTunnelsInstanceIdentifier(nodeId,
+ ifTunnel.getTunnelSource(), ifTunnel.getTunnelDestination());
+ createTunnelToInterfaceMap(tunnelsInstanceIdentifier.toString(), infName, transaction);
+ }
+
+ public static void removeTunnelToInterfaceMap(InstanceIdentifier<Node> nodeId,
+ WriteTransaction transaction,
+ IfTunnel ifTunnel){
+ InstanceIdentifier<Tunnels> tunnelsInstanceIdentifier = org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.utilities.SouthboundUtils.
+ createTunnelsInstanceIdentifier(nodeId,
+ ifTunnel.getTunnelSource(), ifTunnel.getTunnelDestination());
+ transaction.delete(LogicalDatastoreType.OPERATIONAL, tunnelsInstanceIdentifier);
+ }
+
+ public static String getInterfaceForTunnelInstanceIdentifier(String tunnelInstanceId,
+ DataBroker dataBroker) {
+ InstanceIdentifier<TunnelInstanceInterface> id = InstanceIdentifier.builder(TunnelInstanceInterfaceMap.class).
+ child(TunnelInstanceInterface.class, new TunnelInstanceInterfaceKey(tunnelInstanceId)).build();
+ Optional<TunnelInstanceInterface> tunnelInstanceInterfaceOptional = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, dataBroker);
+ if(tunnelInstanceInterfaceOptional.isPresent()){
+ return tunnelInstanceInterfaceOptional.get().getInterfaceName();
+ }
+ return null;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.vpnservice.interfacemgr.listeners;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.vpnservice.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigAddHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigRemoveHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigUpdateHelper;
+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.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.LivenessState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorEvent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+
+/**
+ * This class listens for interface creation/removal/update in Configuration DS.
+ * This is used to handle interfaces for base of-ports.
+ */
+public class AlivenessMonitorListener implements org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorListener {
+ private static final Logger LOG = LoggerFactory.getLogger(AlivenessMonitorListener.class);
+ private DataBroker dataBroker;
+
+ public AlivenessMonitorListener(final DataBroker dataBroker) {
+ this.dataBroker = dataBroker;
+ }
+
+ @Override
+ public void onMonitorEvent(MonitorEvent notification) {
+ Long monitorId = notification.getEventData().getMonitorId();
+ String tunnelInterface = AlivenessMonitorUtils.getInterfaceFromMonitorId(dataBroker, monitorId);
+ if (tunnelInterface == null) {
+ LOG.debug("Either monitoring for interface - {} not started by Interfacemgr or it is not LLDP monitoring", tunnelInterface);
+ return;
+ }
+ LivenessState livenessState = notification.getEventData().getMonitorState();
+ LOG.debug("received monitor event for {} with livenessstate {}", tunnelInterface, livenessState);
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus opState =
+ livenessState == LivenessState.Up ? org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Up :
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
+ InterfaceManagerCommonUtils.setOpStateForInterface(dataBroker, tunnelInterface, opState);
+ }
+
+}
--- /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.listeners;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.vpnservice.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.confighelpers.HwVTEPConfigRemoveHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.confighelpers.HwVTEPInterfaceConfigAddHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.confighelpers.HwVTEPInterfaceConfigUpdateHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.utilities.SouthboundUtils;
+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.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.interfaces._interface.NodeIdentifier;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+
+public class HwVTEPConfigListener extends AsyncDataTreeChangeListenerBase<Interface, HwVTEPConfigListener> {
+ private static final Logger LOG = LoggerFactory.getLogger(HwVTEPConfigListener.class);
+ private DataBroker dataBroker;
+
+ public HwVTEPConfigListener(final DataBroker dataBroker) {
+ super(Interface.class, HwVTEPConfigListener.class);
+ this.dataBroker = dataBroker;
+ }
+
+ @Override
+ protected InstanceIdentifier<Interface> getWildCardPath() {
+ return InstanceIdentifier.create(Interfaces.class).child(Interface.class);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Interface> key, Interface interfaceOld) {
+ // HwVTEPs support only vxlan
+ IfTunnel ifTunnel = interfaceOld.getAugmentation(IfTunnel.class);
+ if (ifTunnel != null && ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
+ ParentRefs parentRefs = interfaceOld.getAugmentation(ParentRefs.class);
+ if (parentRefs != null && parentRefs.getNodeIdentifier() != null) {
+ for(NodeIdentifier nodeIdentifier : parentRefs.getNodeIdentifier()) {
+ if(SouthboundUtils.HWVTEP_TOPOLOGY.equals(nodeIdentifier.getTopologyId())) {
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ RendererConfigRemoveWorker configWorker = new RendererConfigRemoveWorker(key, interfaceOld,
+ SouthboundUtils.createPhysicalSwitchInstanceIdentifier(nodeIdentifier.getNodeId()),
+ SouthboundUtils.createGlobalNodeInstanceIdentifier(dataBroker, nodeIdentifier.getNodeId()));
+ coordinator.enqueueJob(interfaceOld.getName(), configWorker);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Interface> key, Interface interfaceOld, Interface interfaceNew) {
+ // HwVTEPs support only vxlan
+ IfTunnel ifTunnel = interfaceNew.getAugmentation(IfTunnel.class);
+ if (ifTunnel != null && ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
+ ParentRefs parentRefs = interfaceNew.getAugmentation(ParentRefs.class);
+ if (parentRefs != null && parentRefs.getNodeIdentifier() != null) {
+ for(NodeIdentifier nodeIdentifier : parentRefs.getNodeIdentifier()) {
+ if(SouthboundUtils.HWVTEP_TOPOLOGY.equals(nodeIdentifier.getTopologyId())) {
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ RendererConfigUpdateWorker configWorker = new RendererConfigUpdateWorker(key, interfaceNew,
+ SouthboundUtils.createPhysicalSwitchInstanceIdentifier(nodeIdentifier.getNodeId()),
+ SouthboundUtils.createGlobalNodeInstanceIdentifier(dataBroker, nodeIdentifier.getNodeId()), ifTunnel);
+ coordinator.enqueueJob(interfaceNew.getName(), configWorker, 3);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Interface> key, Interface interfaceNew) {
+ // HwVTEPs support only vxlan
+ IfTunnel ifTunnel = interfaceNew.getAugmentation(IfTunnel.class);
+ if (ifTunnel != null && ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
+ ParentRefs parentRefs = interfaceNew.getAugmentation(ParentRefs.class);
+ if (parentRefs != null && parentRefs.getNodeIdentifier() != null) {
+ for(NodeIdentifier nodeIdentifier : parentRefs.getNodeIdentifier()) {
+ if(SouthboundUtils.HWVTEP_TOPOLOGY.equals(nodeIdentifier.getTopologyId())) {
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ RendererConfigAddWorker configWorker = new RendererConfigAddWorker(key, interfaceNew,
+ SouthboundUtils.createPhysicalSwitchInstanceIdentifier(nodeIdentifier.getNodeId()),
+ SouthboundUtils.createGlobalNodeInstanceIdentifier(dataBroker, nodeIdentifier.getNodeId()), ifTunnel);
+ coordinator.enqueueJob(interfaceNew.getName(), configWorker, 3);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ protected HwVTEPConfigListener getDataTreeChangeListener() {
+ return HwVTEPConfigListener.this;
+ }
+
+ private class RendererConfigAddWorker implements Callable<List<ListenableFuture<Void>>> {
+ InstanceIdentifier<Interface> key;
+ Interface interfaceNew;
+ InstanceIdentifier<Node> physicalSwitchNodeId;
+ InstanceIdentifier<Node> globalNodeId;
+ IfTunnel ifTunnel;
+
+ public RendererConfigAddWorker(InstanceIdentifier<Interface> key, Interface interfaceNew,
+ InstanceIdentifier<Node> physicalSwitchNodeId, InstanceIdentifier<Node> globalNodeId, IfTunnel ifTunnel) {
+ this.key = key;
+ this.interfaceNew = interfaceNew;
+ this.physicalSwitchNodeId = physicalSwitchNodeId;
+ this.globalNodeId = globalNodeId;
+ this.ifTunnel = ifTunnel;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ return HwVTEPInterfaceConfigAddHelper.addConfiguration(dataBroker,
+ physicalSwitchNodeId, globalNodeId, interfaceNew, ifTunnel);
+ }
+ }
+
+ private class RendererConfigUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
+ InstanceIdentifier<Interface> key;
+ Interface interfaceNew;
+ InstanceIdentifier<Node> globalNodeId;
+ InstanceIdentifier<Node> physicalSwitchNodeId;
+ IfTunnel ifTunnel;
+
+ public RendererConfigUpdateWorker(InstanceIdentifier<Interface> key, Interface interfaceNew,
+ InstanceIdentifier<Node> physicalSwitchNodeId, InstanceIdentifier<Node> globalNodeId, IfTunnel ifTunnel) {
+ this.key = key;
+ this.interfaceNew = interfaceNew;
+ this.physicalSwitchNodeId = physicalSwitchNodeId;
+ this.ifTunnel = ifTunnel;
+ this.globalNodeId = globalNodeId;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ return HwVTEPInterfaceConfigUpdateHelper.updateConfiguration(dataBroker,
+ physicalSwitchNodeId, globalNodeId, interfaceNew, ifTunnel);
+ }
+ }
+
+ private class RendererConfigRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
+ InstanceIdentifier<Interface> key;
+ Interface interfaceOld;
+ InstanceIdentifier<Node> physicalSwitchNodeId;
+ InstanceIdentifier<Node> globalNodeId;
+
+ public RendererConfigRemoveWorker(InstanceIdentifier<Interface> key, Interface interfaceOld,
+ InstanceIdentifier<Node> physicalSwitchNodeId, InstanceIdentifier<Node> globalNodeId) {
+ this.key = key;
+ this.interfaceOld = interfaceOld;
+ this.physicalSwitchNodeId = physicalSwitchNodeId;
+ this.globalNodeId = globalNodeId;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ return HwVTEPConfigRemoveHelper.removeConfiguration(dataBroker,
+ interfaceOld, globalNodeId, physicalSwitchNodeId);
+ }
+ }
+}
\ 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.interfacemgr.listeners;
+
+import com.google.common.util.concurrent.ListenableFuture;
+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.vpnservice.datastoreutils.AsyncDataChangeListenerBase;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.statehelpers.HwVTEPInterfaceStateRemoveHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.statehelpers.HwVTEPInterfaceStateUpdateHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.Tunnels;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+
+public class HwVTEPTunnelsStateListener extends AsyncDataChangeListenerBase<Tunnels, HwVTEPTunnelsStateListener> {
+ private static final Logger LOG = LoggerFactory.getLogger(HwVTEPTunnelsStateListener.class);
+ private DataBroker dataBroker;
+
+ public HwVTEPTunnelsStateListener(DataBroker dataBroker) {
+ super(Tunnels.class, HwVTEPTunnelsStateListener.class);
+ this.dataBroker = dataBroker;
+ }
+
+ @Override
+ protected InstanceIdentifier<Tunnels> getWildCardPath() {
+ return InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class)
+ .child(Node.class).augmentation(PhysicalSwitchAugmentation.class).child(Tunnels.class).build();
+ }
+
+ @Override
+ protected DataChangeListener getDataChangeListener() {
+ return HwVTEPTunnelsStateListener.this;
+ }
+
+ @Override
+ protected AsyncDataBroker.DataChangeScope getDataChangeScope() {
+ return AsyncDataBroker.DataChangeScope.BASE;
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Tunnels> identifier, Tunnels tunnel) {
+ LOG.debug("Received Remove DataChange Notification for identifier: {}, physicalSwitchAugmentation: {}",
+ identifier, tunnel);
+ DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
+ RendererStateRemoveWorker rendererStateRemoveWorker = new RendererStateRemoveWorker(identifier, tunnel);
+ jobCoordinator.enqueueJob(tunnel.getTunnelUuid().getValue(), rendererStateRemoveWorker);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Tunnels> identifier, Tunnels tunnelOld,
+ Tunnels tunnelNew) {
+ LOG.debug("Received Update Tunnel Update Notification for identifier: {}", identifier);
+ DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
+ RendererStateUpdateWorker rendererStateUpdateWorker = new RendererStateUpdateWorker(identifier, tunnelNew, tunnelOld);
+ jobCoordinator.enqueueJob(tunnelNew.getTunnelUuid().getValue(), rendererStateUpdateWorker);
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Tunnels> identifier, Tunnels tunnelNew) {
+ LOG.debug("Received Add DataChange Notification for identifier: {}, tunnels: {}",
+ identifier, tunnelNew);
+ DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
+ RendererStateAddWorker rendererStateAddWorker = new RendererStateAddWorker(identifier, tunnelNew);
+ jobCoordinator.enqueueJob(tunnelNew.getTunnelUuid().getValue(), rendererStateAddWorker);
+ }
+
+ private class RendererStateUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
+ InstanceIdentifier<Tunnels> instanceIdentifier;
+ Tunnels tunnelsNew;
+ Tunnels tunnelsOld;
+
+ public RendererStateUpdateWorker(InstanceIdentifier<Tunnels> instanceIdentifier,
+ Tunnels tunnelsNew, Tunnels tunnelsOld) {
+ this.instanceIdentifier = instanceIdentifier;
+ this.tunnelsNew = tunnelsNew;
+ this.tunnelsOld = tunnelsOld;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ // If another renderer(for eg : CSS) needs to be supported, check can be performed here
+ // to call the respective helpers.
+ return HwVTEPInterfaceStateUpdateHelper.updatePhysicalSwitch(dataBroker,
+ instanceIdentifier, tunnelsOld, tunnelsNew);
+ }
+ }
+
+ private class RendererStateAddWorker implements Callable<List<ListenableFuture<Void>>> {
+ InstanceIdentifier<Tunnels> instanceIdentifier;
+ Tunnels tunnelsNew;
+
+ public RendererStateAddWorker(InstanceIdentifier<Tunnels> instanceIdentifier,
+ Tunnels tunnelsNew) {
+ this.instanceIdentifier = instanceIdentifier;
+ this.tunnelsNew = tunnelsNew;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ // If another renderer(for eg : CSS) needs to be supported, check can be performed here
+ // to call the respective helpers.
+ return HwVTEPInterfaceStateUpdateHelper.startBfdMonitoring(dataBroker, instanceIdentifier, tunnelsNew);
+ }
+ }
+
+ private class RendererStateRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
+ InstanceIdentifier<Tunnels> instanceIdentifier;
+ Tunnels tunnel;
+
+ public RendererStateRemoveWorker(InstanceIdentifier<Tunnels> instanceIdentifier,
+ Tunnels tunnel) {
+ this.instanceIdentifier = instanceIdentifier;
+ this.tunnel = tunnel;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ // If another renderer(for eg : CSS) needs to be supported, check can be performed here
+ // to call the respective helpers.
+ return HwVTEPInterfaceStateRemoveHelper.removeExternalTunnel(dataBroker, instanceIdentifier);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.vpnservice.interfacemgr.listeners;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.idmanager.IdManager;
+import org.opendaylight.vpnservice.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigAddHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigRemoveHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigUpdateHelper;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+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.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+
+/**
+ * This class listens for interface creation/removal/update in Configuration DS.
+ * This is used to handle interfaces for base of-ports.
+ */
+public class InterfaceConfigListener extends AsyncDataTreeChangeListenerBase<Interface, InterfaceConfigListener> {
+ private static final Logger LOG = LoggerFactory.getLogger(InterfaceConfigListener.class);
+ private DataBroker dataBroker;
+ private IdManagerService idManager;
+ private AlivenessMonitorService alivenessMonitorService;
+ private IMdsalApiManager mdsalApiManager;
+ private static final int MAX_RETRIES = 3;
+
+ public InterfaceConfigListener(final DataBroker dataBroker, final IdManagerService idManager,
+ final AlivenessMonitorService alivenessMonitorService,
+ final IMdsalApiManager mdsalApiManager) {
+ super(Interface.class, InterfaceConfigListener.class);
+ this.dataBroker = dataBroker;
+ this.idManager = idManager;
+ this.alivenessMonitorService = alivenessMonitorService;
+ this.mdsalApiManager = mdsalApiManager;
+ }
+
+ @Override
+ protected InstanceIdentifier<Interface> getWildCardPath() {
+ return InstanceIdentifier.create(Interfaces.class).child(Interface.class);
+ }
+
+ @Override
+ protected InterfaceConfigListener getDataTreeChangeListener() {
+ return InterfaceConfigListener.this;
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Interface> key, Interface interfaceOld) {
+ LOG.debug("Received Interface Remove Event: {}, {}", key, interfaceOld);
+ String ifName = interfaceOld.getName();
+ ParentRefs parentRefs = interfaceOld.getAugmentation(ParentRefs.class);
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ RendererConfigRemoveWorker configWorker = new RendererConfigRemoveWorker(key, interfaceOld, ifName, parentRefs);
+ coordinator.enqueueJob(ifName, configWorker, MAX_RETRIES);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Interface> key, Interface interfaceOld, Interface interfaceNew) {
+ LOG.debug("Received Interface Update Event: {}, {}, {}", key, interfaceOld, interfaceNew);
+ String ifNameNew = interfaceNew.getName();
+ ParentRefs parentRefs = interfaceNew.getAugmentation(ParentRefs.class);
+ if (parentRefs == null || parentRefs.getDatapathNodeIdentifier() == null && parentRefs.getParentInterface() == null) {
+ LOG.error("parent refs not specified for {}",interfaceNew.getName());
+ return;
+ }
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ RendererConfigUpdateWorker worker = new RendererConfigUpdateWorker(key, interfaceOld, interfaceNew, ifNameNew);
+ coordinator.enqueueJob(ifNameNew, worker, MAX_RETRIES);
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Interface> key, Interface interfaceNew) {
+ LOG.debug("Received Interface Add Event: {}, {}", key, interfaceNew);
+ String ifName = interfaceNew.getName();
+ ParentRefs parentRefs = interfaceNew.getAugmentation(ParentRefs.class);
+ if (parentRefs == null || parentRefs.getDatapathNodeIdentifier() == null && parentRefs.getParentInterface() == null) {
+ LOG.error("parent refs not specified for {}",interfaceNew.getName());
+ return;
+ }
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ RendererConfigAddWorker configWorker = new RendererConfigAddWorker(key, interfaceNew, parentRefs, ifName);
+ coordinator.enqueueJob(ifName, configWorker, MAX_RETRIES);
+ }
+
+ private class RendererConfigAddWorker implements Callable<List<ListenableFuture<Void>>> {
+ InstanceIdentifier<Interface> key;
+ Interface interfaceNew;
+ String portName;
+ ParentRefs parentRefs;
+
+ public RendererConfigAddWorker(InstanceIdentifier<Interface> key, Interface interfaceNew,
+ ParentRefs parentRefs, String portName) {
+ this.key = key;
+ this.interfaceNew = interfaceNew;
+ this.portName = portName;
+ this.parentRefs = parentRefs;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ // If another renderer(for eg : CSS) needs to be supported, check can be performed here
+ // to call the respective helpers.
+ return OvsInterfaceConfigAddHelper.addConfiguration(dataBroker, parentRefs, interfaceNew,
+ idManager, alivenessMonitorService, mdsalApiManager);
+ }
+
+ @Override
+ public String toString() {
+ return "RendererConfigAddWorker{" +
+ "key=" + key +
+ ", interfaceNew=" + interfaceNew +
+ ", portName='" + portName + '\'' +
+ '}';
+ }
+ }
+
+ /**
+ *
+ */
+ private class RendererConfigUpdateWorker implements Callable {
+ InstanceIdentifier<Interface> key;
+ Interface interfaceOld;
+ Interface interfaceNew;
+ String portNameNew;
+
+ public RendererConfigUpdateWorker(InstanceIdentifier<Interface> key, Interface interfaceOld,
+ Interface interfaceNew, String portNameNew) {
+ this.key = key;
+ this.interfaceOld = interfaceOld;
+ this.interfaceNew = interfaceNew;
+ this.portNameNew = portNameNew;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ // If another renderer(for eg : CSS) needs to be supported, check can be performed here
+ // to call the respective helpers.
+ return OvsInterfaceConfigUpdateHelper.updateConfiguration(dataBroker, alivenessMonitorService, idManager,
+ mdsalApiManager, interfaceNew, interfaceOld);
+ }
+
+ @Override
+ public String toString() {
+ return "RendererConfigUpdateWorker{" +
+ "key=" + key +
+ ", interfaceOld=" + interfaceOld +
+ ", interfaceNew=" + interfaceNew +
+ ", portNameNew='" + portNameNew + '\'' +
+ '}';
+ }
+ }
+
+ /**
+ *
+ */
+ private class RendererConfigRemoveWorker implements Callable {
+ InstanceIdentifier<Interface> key;
+ Interface interfaceOld;
+ String portName;
+ ParentRefs parentRefs;
+
+ public RendererConfigRemoveWorker(InstanceIdentifier<Interface> key, Interface interfaceOld, String portName,
+ ParentRefs parentRefs) {
+ this.key = key;
+ this.interfaceOld = interfaceOld;
+ this.portName = portName;
+ this.parentRefs = parentRefs;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ // If another renderer(for eg : CSS) needs to be supported, check can be performed here
+ // to call the respective helpers.
+ return OvsInterfaceConfigRemoveHelper.removeConfiguration(dataBroker, alivenessMonitorService,
+ interfaceOld, idManager, mdsalApiManager, parentRefs);
+ }
+
+ @Override
+ public String toString() {
+ return "RendererConfigRemoveWorker{" +
+ "key=" + key +
+ ", interfaceOld=" + interfaceOld +
+ ", portName='" + portName + '\'' +
+ '}';
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.interfacemgr.listeners;
+
+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.idmanager.IdManager;
+import org.opendaylight.vpnservice.datastoreutils.AsyncDataChangeListenerBase;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.statehelpers.OvsInterfaceStateAddHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.statehelpers.OvsInterfaceStateRemoveHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.statehelpers.OvsInterfaceStateRemoveHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.statehelpers.OvsInterfaceStateUpdateHelper;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.Callable;
+
+/**
+ *
+ * This Class is a Data Change Listener for FlowCapableNodeConnector updates.
+ * This creates an entry in the interface-state OperDS for every node-connector used.
+ *
+ * NOTE: This class just creates an ifstate entry whose interface-name will be the same as the node-connector portname.
+ * If PortName is not unique across DPNs, this implementation can have problems.
+ */
+
+public class InterfaceInventoryStateListener extends AsyncDataChangeListenerBase<FlowCapableNodeConnector, InterfaceInventoryStateListener> implements AutoCloseable{
+ private static final Logger LOG = LoggerFactory.getLogger(InterfaceInventoryStateListener.class);
+ private DataBroker dataBroker;
+ private IdManagerService idManager;
+ private IMdsalApiManager mdsalApiManager;
+ private AlivenessMonitorService alivenessMonitorService;
+
+ public InterfaceInventoryStateListener(final DataBroker dataBroker, final IdManagerService idManager,
+ final IMdsalApiManager mdsalApiManager, final AlivenessMonitorService alivenessMonitorService) {
+ super(FlowCapableNodeConnector.class, InterfaceInventoryStateListener.class);
+ this.dataBroker = dataBroker;
+ this.idManager = idManager;
+ this.mdsalApiManager = mdsalApiManager;
+ this.alivenessMonitorService = alivenessMonitorService;
+ }
+
+ @Override
+ protected InstanceIdentifier<FlowCapableNodeConnector> getWildCardPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class).child(NodeConnector.class)
+ .augmentation(FlowCapableNodeConnector.class);
+ }
+
+ @Override
+ protected DataChangeListener getDataChangeListener() {
+ return InterfaceInventoryStateListener.this;
+ }
+
+ @Override
+ protected AsyncDataBroker.DataChangeScope getDataChangeScope() {
+ return AsyncDataBroker.DataChangeScope.ONE;
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<FlowCapableNodeConnector> key,
+ FlowCapableNodeConnector flowCapableNodeConnectorOld) {
+ LOG.debug("Received NodeConnector Remove Event: {}, {}", key, flowCapableNodeConnectorOld);
+ String portName = flowCapableNodeConnectorOld.getName();
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+
+ InterfaceStateRemoveWorker interfaceStateRemoveWorker = new InterfaceStateRemoveWorker(idManager,
+ key, flowCapableNodeConnectorOld, portName);
+ coordinator.enqueueJob(portName, interfaceStateRemoveWorker);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<FlowCapableNodeConnector> key, FlowCapableNodeConnector fcNodeConnectorOld,
+ FlowCapableNodeConnector fcNodeConnectorNew) {
+ LOG.debug("Received NodeConnector Update Event: {}, {}, {}", key, fcNodeConnectorOld, fcNodeConnectorNew);
+ String portName = fcNodeConnectorNew.getName();
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+
+ InterfaceStateUpdateWorker interfaceStateUpdateWorker = new InterfaceStateUpdateWorker(key, fcNodeConnectorOld,
+ fcNodeConnectorNew, portName);
+ coordinator.enqueueJob(portName, interfaceStateUpdateWorker);
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<FlowCapableNodeConnector> key, FlowCapableNodeConnector fcNodeConnectorNew) {
+ LOG.debug("Received NodeConnector Add Event: {}, {}", key, fcNodeConnectorNew);
+ String portName = fcNodeConnectorNew.getName();
+ NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
+
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ InterfaceStateAddWorker ifStateAddWorker = new InterfaceStateAddWorker(idManager, nodeConnectorId,
+ fcNodeConnectorNew, portName);
+ coordinator.enqueueJob(portName, ifStateAddWorker);
+ }
+
+ private class InterfaceStateAddWorker implements Callable {
+ private final NodeConnectorId nodeConnectorId;
+ private final FlowCapableNodeConnector fcNodeConnectorNew;
+ private final String portName;
+ private final IdManagerService idManager;
+
+ public InterfaceStateAddWorker(IdManagerService idManager, NodeConnectorId nodeConnectorId,
+ FlowCapableNodeConnector fcNodeConnectorNew,
+ String portName) {
+ this.nodeConnectorId = nodeConnectorId;
+ this.fcNodeConnectorNew = fcNodeConnectorNew;
+ this.portName = portName;
+ this.idManager = idManager;
+ }
+
+ @Override
+ public Object call() throws Exception {
+ // If another renderer(for eg : CSS) needs to be supported, check can be performed here
+ // to call the respective helpers.
+ return OvsInterfaceStateAddHelper.addState(dataBroker, idManager, mdsalApiManager, alivenessMonitorService, nodeConnectorId,
+ portName, fcNodeConnectorNew);
+ }
+
+ @Override
+ public String toString() {
+ return "InterfaceStateAddWorker{" +
+ "nodeConnectorId=" + nodeConnectorId +
+ ", fcNodeConnectorNew=" + fcNodeConnectorNew +
+ ", portName='" + portName + '\'' +
+ '}';
+ }
+ }
+
+ private class InterfaceStateUpdateWorker implements Callable {
+ private InstanceIdentifier<FlowCapableNodeConnector> key;
+ private final FlowCapableNodeConnector fcNodeConnectorOld;
+ private final FlowCapableNodeConnector fcNodeConnectorNew;
+ private String portName;
+
+
+ public InterfaceStateUpdateWorker(InstanceIdentifier<FlowCapableNodeConnector> key,
+ FlowCapableNodeConnector fcNodeConnectorOld,
+ FlowCapableNodeConnector fcNodeConnectorNew,
+ String portName) {
+ this.key = key;
+ this.fcNodeConnectorOld = fcNodeConnectorOld;
+ this.fcNodeConnectorNew = fcNodeConnectorNew;
+ this.portName = portName;
+ }
+
+ @Override
+ public Object call() throws Exception {
+ // If another renderer(for eg : CSS) needs to be supported, check can be performed here
+ // to call the respective helpers.
+ return OvsInterfaceStateUpdateHelper.updateState(key, alivenessMonitorService, dataBroker, portName,
+ fcNodeConnectorNew, fcNodeConnectorOld);
+ }
+
+ @Override
+ public String toString() {
+ return "InterfaceStateUpdateWorker{" +
+ "key=" + key +
+ ", fcNodeConnectorOld=" + fcNodeConnectorOld +
+ ", fcNodeConnectorNew=" + fcNodeConnectorNew +
+ ", portName='" + portName + '\'' +
+ '}';
+ }
+ }
+
+ private class InterfaceStateRemoveWorker implements Callable {
+ InstanceIdentifier<FlowCapableNodeConnector> key;
+ FlowCapableNodeConnector fcNodeConnectorOld;
+ private final String portName;
+ private final IdManagerService idManager;
+
+ public InterfaceStateRemoveWorker(IdManagerService idManager,
+ InstanceIdentifier<FlowCapableNodeConnector> key,
+ FlowCapableNodeConnector fcNodeConnectorOld,
+ String portName) {
+ this.key = key;
+ this.fcNodeConnectorOld = fcNodeConnectorOld;
+ this.portName = portName;
+ this.idManager = idManager;
+ }
+
+ @Override
+ public Object call() throws Exception {
+ // If another renderer(for eg : CSS) needs to be supported, check can be performed here
+ // to call the respective helpers.
+ return OvsInterfaceStateRemoveHelper.removeState(idManager, mdsalApiManager, alivenessMonitorService,
+ key, dataBroker, portName, fcNodeConnectorOld);
+ }
+
+ @Override
+ public String toString() {
+ return "InterfaceStateRemoveWorker{" +
+ "key=" + key +
+ ", fcNodeConnectorOld=" + fcNodeConnectorOld +
+ ", portName='" + portName + '\'' +
+ '}';
+ }
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.interfacemgr.listeners;
+
+import com.google.common.util.concurrent.ListenableFuture;
+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.vpnservice.datastoreutils.AsyncDataChangeListenerBase;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.statehelpers.OvsInterfaceTopologyStateAddHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.statehelpers.OvsInterfaceTopologyStateRemoveHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.statehelpers.OvsInterfaceTopologyStateUpdateHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+
+public class InterfaceTopologyStateListener extends AsyncDataChangeListenerBase<OvsdbBridgeAugmentation, InterfaceTopologyStateListener> {
+ private static final Logger LOG = LoggerFactory.getLogger(InterfaceTopologyStateListener.class);
+ private DataBroker dataBroker;
+
+ public InterfaceTopologyStateListener(DataBroker dataBroker) {
+ super(OvsdbBridgeAugmentation.class, InterfaceTopologyStateListener.class);
+ this.dataBroker = dataBroker;
+ }
+
+ @Override
+ protected InstanceIdentifier<OvsdbBridgeAugmentation> getWildCardPath() {
+ return InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class)
+ .child(Node.class).augmentation(OvsdbBridgeAugmentation.class).build();
+ }
+
+ @Override
+ protected DataChangeListener getDataChangeListener() {
+ return InterfaceTopologyStateListener.this;
+ }
+
+ @Override
+ protected AsyncDataBroker.DataChangeScope getDataChangeScope() {
+ return AsyncDataBroker.DataChangeScope.ONE;
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<OvsdbBridgeAugmentation> identifier, OvsdbBridgeAugmentation bridgeOld) {
+ LOG.debug("Received Remove DataChange Notification for identifier: {}, ovsdbBridgeAugmentation: {}",
+ identifier, bridgeOld);
+ DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
+ RendererStateRemoveWorker rendererStateRemoveWorker = new RendererStateRemoveWorker(identifier, bridgeOld);
+ jobCoordinator.enqueueJob(bridgeOld.getBridgeName().getValue(), rendererStateRemoveWorker);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<OvsdbBridgeAugmentation> identifier, OvsdbBridgeAugmentation bridgeOld,
+ OvsdbBridgeAugmentation bridgeNew) {
+ LOG.debug("Received Update DataChange Notification for identifier: {}, ovsdbBridgeAugmentation old: {}, new: {}.",
+ identifier, bridgeOld, bridgeNew);
+ if(bridgeOld.getDatapathId()== null && bridgeNew.getDatapathId()!= null){
+ DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
+ RendererStateAddWorker rendererStateAddWorker = new RendererStateAddWorker(identifier, bridgeNew);
+ jobCoordinator.enqueueJob(bridgeNew.getBridgeName().getValue(), rendererStateAddWorker);
+ } else if(!bridgeOld.getDatapathId().equals(bridgeNew.getDatapathId())){
+ DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
+ RendererStateUpdateWorker rendererStateAddWorker = new RendererStateUpdateWorker(identifier, bridgeNew, bridgeOld);
+ jobCoordinator.enqueueJob(bridgeNew.getBridgeName().getValue(), rendererStateAddWorker);
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<OvsdbBridgeAugmentation> identifier, OvsdbBridgeAugmentation bridgeNew) {
+ LOG.debug("Received Add DataChange Notification for identifier: {}, ovsdbBridgeAugmentation: {}",
+ identifier, bridgeNew);
+ DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
+ RendererStateAddWorker rendererStateAddWorker = new RendererStateAddWorker(identifier, bridgeNew);
+ jobCoordinator.enqueueJob(bridgeNew.getBridgeName().getValue() + bridgeNew.getDatapathId(), rendererStateAddWorker);
+ }
+
+ private class RendererStateAddWorker implements Callable<List<ListenableFuture<Void>>> {
+ InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier;
+ OvsdbBridgeAugmentation bridgeNew;
+
+
+ public RendererStateAddWorker(InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier,
+ OvsdbBridgeAugmentation bridgeNew) {
+ this.instanceIdentifier = instanceIdentifier;
+ this.bridgeNew = bridgeNew;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ // If another renderer(for eg : CSS) needs to be supported, check can be performed here
+ // to call the respective helpers.
+ return OvsInterfaceTopologyStateAddHelper.addPortToBridge(instanceIdentifier,
+ bridgeNew, dataBroker);
+ }
+ }
+
+ private class RendererStateRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
+ InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier;
+ OvsdbBridgeAugmentation bridgeNew;
+
+
+ public RendererStateRemoveWorker(InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier,
+ OvsdbBridgeAugmentation bridgeNew) {
+ this.instanceIdentifier = instanceIdentifier;
+ this.bridgeNew = bridgeNew;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ // If another renderer(for eg : CSS) needs to be supported, check can be performed here
+ // to call the respective helpers.
+ return OvsInterfaceTopologyStateRemoveHelper.removePortFromBridge(instanceIdentifier,
+ bridgeNew, dataBroker);
+ }
+ }
+ private class RendererStateUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
+ InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier;
+ OvsdbBridgeAugmentation bridgeNew;
+ OvsdbBridgeAugmentation bridgeOld;
+
+
+ public RendererStateUpdateWorker(InstanceIdentifier<OvsdbBridgeAugmentation> instanceIdentifier,
+ OvsdbBridgeAugmentation bridgeNew, OvsdbBridgeAugmentation bridgeOld) {
+ this.instanceIdentifier = instanceIdentifier;
+ this.bridgeNew = bridgeNew;
+ this.bridgeOld = bridgeOld;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ // If another renderer(for eg : CSS) needs to be supported, check can be performed here
+ // to call the respective helpers.
+ return OvsInterfaceTopologyStateUpdateHelper.updateBridgeRefEntry(instanceIdentifier,
+ bridgeNew, bridgeOld, dataBroker);
+ }
+ }
+}
\ 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.interfacemgr.listeners;
+
+import com.google.common.util.concurrent.ListenableFuture;
+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.vpnservice.datastoreutils.AsyncDataChangeListenerBase;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.statehelpers.OvsInterfaceTopologyStateUpdateHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+
+public class TerminationPointStateListener extends AsyncDataChangeListenerBase<OvsdbTerminationPointAugmentation, TerminationPointStateListener> {
+ private static final Logger LOG = LoggerFactory.getLogger(TerminationPointStateListener.class);
+ private DataBroker dataBroker;
+
+ public TerminationPointStateListener(DataBroker dataBroker) {
+ super(OvsdbTerminationPointAugmentation.class, TerminationPointStateListener.class);
+ this.dataBroker = dataBroker;
+ }
+
+ @Override
+ protected InstanceIdentifier<OvsdbTerminationPointAugmentation> getWildCardPath() {
+ return InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class)
+ .child(Node.class).child(TerminationPoint.class).augmentation(OvsdbTerminationPointAugmentation.class).build();
+ }
+
+ @Override
+ protected DataChangeListener getDataChangeListener() {
+ return TerminationPointStateListener.this;
+ }
+
+ @Override
+ protected AsyncDataBroker.DataChangeScope getDataChangeScope() {
+ return AsyncDataBroker.DataChangeScope.SUBTREE;
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<OvsdbTerminationPointAugmentation> identifier,
+ OvsdbTerminationPointAugmentation tpOld) {
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<OvsdbTerminationPointAugmentation> identifier,
+ OvsdbTerminationPointAugmentation tpOld,
+ OvsdbTerminationPointAugmentation tpNew) {
+ LOG.debug("Received Update DataChange Notification for ovsdb termination point {}", tpNew.getName());
+ if (tpNew.getInterfaceBfdStatus() != null &&
+ !tpNew.getInterfaceBfdStatus().equals(tpOld.getInterfaceBfdStatus())) {
+ LOG.trace("Bfd Status changed for ovsdb termination point identifier: {}, old: {}, new: {}.",
+ identifier, tpOld, tpNew);
+ DataStoreJobCoordinator jobCoordinator = DataStoreJobCoordinator.getInstance();
+ RendererStateUpdateWorker rendererStateAddWorker = new RendererStateUpdateWorker(identifier, tpNew, tpOld);
+ jobCoordinator.enqueueJob(tpNew.getName(), rendererStateAddWorker);
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<OvsdbTerminationPointAugmentation> identifier,
+ OvsdbTerminationPointAugmentation tpNew) {
+
+ }
+
+ private class RendererStateUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
+ InstanceIdentifier<OvsdbTerminationPointAugmentation> instanceIdentifier;
+ OvsdbTerminationPointAugmentation terminationPointNew;
+ OvsdbTerminationPointAugmentation terminationPointOld;
+
+
+ public RendererStateUpdateWorker(InstanceIdentifier<OvsdbTerminationPointAugmentation> instanceIdentifier,
+ OvsdbTerminationPointAugmentation tpNew, OvsdbTerminationPointAugmentation tpOld) {
+ this.instanceIdentifier = instanceIdentifier;
+ this.terminationPointNew = tpNew;
+ this.terminationPointOld = tpOld;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ // If another renderer(for eg : CSS) needs to be supported, check can be performed here
+ // to call the respective helpers.
+ return OvsInterfaceTopologyStateUpdateHelper.updateTunnelState(dataBroker,
+ terminationPointNew, terminationPointOld);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.listeners;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.idmanager.IdManager;
+import org.opendaylight.vpnservice.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsVlanMemberConfigAddHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsVlanMemberConfigRemoveHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsVlanMemberConfigUpdateHelper;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+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.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+
+public class VlanMemberConfigListener extends AsyncDataTreeChangeListenerBase<Interface, VlanMemberConfigListener> {
+ private static final Logger LOG = LoggerFactory.getLogger(VlanMemberConfigListener.class);
+ private DataBroker dataBroker;
+ private IdManagerService idManager;
+ private AlivenessMonitorService alivenessMonitorService;
+ private IMdsalApiManager mdsalApiManager;
+
+ public VlanMemberConfigListener(final DataBroker dataBroker, final IdManagerService idManager,
+ final AlivenessMonitorService alivenessMonitorService,
+ final IMdsalApiManager mdsalApiManager) {
+ super(Interface.class, VlanMemberConfigListener.class);
+ this.dataBroker = dataBroker;
+ this.idManager = idManager;
+ this.alivenessMonitorService = alivenessMonitorService;
+ this.mdsalApiManager = mdsalApiManager;
+ }
+
+ @Override
+ protected InstanceIdentifier<Interface> getWildCardPath() {
+ return InstanceIdentifier.create(Interfaces.class).child(Interface.class);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Interface> key, Interface interfaceOld) {
+ IfL2vlan ifL2vlan = interfaceOld.getAugmentation(IfL2vlan.class);
+ if (ifL2vlan == null || IfL2vlan.L2vlanMode.TrunkMember != ifL2vlan.getL2vlanMode()) {
+ return;
+ }
+
+ ParentRefs parentRefs = interfaceOld.getAugmentation(ParentRefs.class);
+ if (parentRefs == null) {
+ LOG.error("Attempt to remove Vlan Trunk-Member {} without a parent interface", interfaceOld);
+ return;
+ }
+
+ String lowerLayerIf = parentRefs.getParentInterface();
+ if (lowerLayerIf.equals(interfaceOld.getName())) {
+ LOG.error("Attempt to remove Vlan Trunk-Member {} with same parent interface name.", interfaceOld);
+ return;
+ }
+
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ RendererConfigRemoveWorker removeWorker = new RendererConfigRemoveWorker(key, interfaceOld, parentRefs, ifL2vlan);
+ coordinator.enqueueJob(lowerLayerIf, removeWorker);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Interface> key, Interface interfaceOld, Interface interfaceNew) {
+ IfL2vlan ifL2vlanNew = interfaceNew.getAugmentation(IfL2vlan.class);
+ if (ifL2vlanNew == null || IfL2vlan.L2vlanMode.TrunkMember != ifL2vlanNew.getL2vlanMode()) {
+ return;
+ }
+
+ ParentRefs parentRefsNew = interfaceNew.getAugmentation(ParentRefs.class);
+ if (parentRefsNew == null) {
+ LOG.error("Configuration Error. Attempt to update Vlan Trunk-Member {} without a " +
+ "parent interface", interfaceNew);
+ return;
+ }
+
+ String lowerLayerIf = parentRefsNew.getParentInterface();
+ if (lowerLayerIf.equals(interfaceNew.getName())) {
+ LOG.error("Configuration Error. Attempt to update Vlan Trunk-Member {} with same parent " +
+ "interface name.", interfaceNew);
+ return;
+ }
+
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ RendererConfigUpdateWorker updateWorker = new RendererConfigUpdateWorker(key, interfaceNew, interfaceOld,
+ parentRefsNew, ifL2vlanNew);
+ coordinator.enqueueJob(lowerLayerIf, updateWorker);
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Interface> key, Interface interfaceNew) {
+ IfL2vlan ifL2vlan = interfaceNew.getAugmentation(IfL2vlan.class);
+ if (ifL2vlan == null || IfL2vlan.L2vlanMode.TrunkMember != ifL2vlan.getL2vlanMode()) {
+ return;
+ }
+
+ ParentRefs parentRefs = interfaceNew.getAugmentation(ParentRefs.class);
+ if (parentRefs == null) {
+ return;
+ }
+
+ String lowerLayerIf = parentRefs.getParentInterface();
+ if (lowerLayerIf.equals(interfaceNew.getName())) {
+ LOG.error("Attempt to add Vlan Trunk-Member {} with same parent interface name.", interfaceNew);
+ return;
+ }
+
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ RendererConfigAddWorker configWorker = new RendererConfigAddWorker(key, interfaceNew, parentRefs, ifL2vlan);
+ coordinator.enqueueJob(lowerLayerIf, configWorker);
+ }
+
+ @Override
+ protected VlanMemberConfigListener getDataTreeChangeListener() {
+ return VlanMemberConfigListener.this;
+ }
+
+ private class RendererConfigAddWorker implements Callable<List<ListenableFuture<Void>>> {
+ InstanceIdentifier<Interface> key;
+ Interface interfaceNew;
+ IfL2vlan ifL2vlan;
+ ParentRefs parentRefs;
+
+ public RendererConfigAddWorker(InstanceIdentifier<Interface> key, Interface interfaceNew,
+ ParentRefs parentRefs, IfL2vlan ifL2vlan) {
+ this.key = key;
+ this.interfaceNew = interfaceNew;
+ this.ifL2vlan = ifL2vlan;
+ this.parentRefs = parentRefs;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ // If another renderer(for eg : CSS) needs to be supported, check can be performed here
+ // to call the respective helpers.
+ return OvsVlanMemberConfigAddHelper.addConfiguration(dataBroker, parentRefs, interfaceNew,
+ ifL2vlan, idManager);
+ }
+ }
+
+ private class RendererConfigUpdateWorker implements Callable<List<ListenableFuture<Void>>> {
+ InstanceIdentifier<Interface> key;
+ Interface interfaceNew;
+ Interface interfaceOld;
+ IfL2vlan ifL2vlanNew;
+ ParentRefs parentRefsNew;
+
+ public RendererConfigUpdateWorker(InstanceIdentifier<Interface> key, Interface interfaceNew,
+ Interface interfaceOld, ParentRefs parentRefsNew, IfL2vlan ifL2vlanNew) {
+ this.key = key;
+ this.interfaceNew = interfaceNew;
+ this.interfaceOld = interfaceOld;
+ this.ifL2vlanNew = ifL2vlanNew;
+ this.parentRefsNew = parentRefsNew;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ // If another renderer(for eg : CSS) needs to be supported, check can be performed here
+ // to call the respective helpers.
+ return OvsVlanMemberConfigUpdateHelper.updateConfiguration(dataBroker, alivenessMonitorService,
+ parentRefsNew, interfaceOld, ifL2vlanNew, interfaceNew, idManager, mdsalApiManager);
+ }
+ }
+
+ private class RendererConfigRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
+ InstanceIdentifier<Interface> key;
+ Interface interfaceOld;
+ IfL2vlan ifL2vlan;
+ ParentRefs parentRefs;
+
+ public RendererConfigRemoveWorker(InstanceIdentifier<Interface> key, Interface interfaceOld,
+ ParentRefs parentRefs, IfL2vlan ifL2vlan) {
+ this.key = key;
+ this.interfaceOld = interfaceOld;
+ this.ifL2vlan = ifL2vlan;
+ this.parentRefs = parentRefs;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ // If another renderer(for eg : CSS) needs to be supported, check can be performed here
+ // to call the respective helpers.
+ return OvsVlanMemberConfigRemoveHelper.removeConfiguration(dataBroker, parentRefs, interfaceOld,
+ ifL2vlan, idManager);
+ }
+ }
+}
\ 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.interfacemgr.pmcounters;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class CounterForEntriesPerOFTable implements CounterForEntriesPerOFTableMBean{
+
+ Map<String, Integer> counterCache = new HashMap<String, Integer>();
+ public static Map counterMap = new HashMap<String,String>();
+ public void invokePMManagedObjects(Map<String, Integer> map) {
+ setCounterDetails(map);
+ }
+
+ public Map<String, Integer> getCounterDetails() {
+ return counterCache;
+ }
+
+ public synchronized void setCounterDetails(Map<String, Integer> map) {
+ counterCache = map;
+ }
+
+ public Map<String, String> retrieveCounterMap(){
+ counterMap = (HashMap) counterCache;
+ return counterMap;
+ }
+
+}
--- /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.pmcounters;
+
+import java.util.Map;
+
+public interface CounterForEntriesPerOFTableMBean {
+ //-----------
+ // operations
+ //-----------
+ public void setCounterDetails(Map<String, Integer> map);
+ public Map<String, Integer> getCounterDetails();
+ //-----------
+ // attributes
+ //-----------
+ public void invokePMManagedObjects(Map<String, Integer> map);
+ public Map<String, String> retrieveCounterMap();
+}
--- /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.pmcounters;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class CounterForOFPortBytesReceive implements CounterForOFPortBytesReceiveMBean{
+
+ Map<String, Integer> counterCache = new HashMap<String, Integer>();
+ public static Map counterMap = new HashMap<String,String>();
+ public void invokePMManagedObjects(Map<String, Integer> map) {
+ setCounterDetails(map);
+ }
+
+ public Map<String, Integer> getCounterDetails() {
+ return counterCache;
+ }
+
+ public synchronized void setCounterDetails(Map<String, Integer> map) {
+ counterCache = map;
+ }
+
+ public Map<String, String> retrieveCounterMap(){
+ counterMap = (HashMap) counterCache;
+ return counterMap;
+ }
+
+}
--- /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.pmcounters;
+
+import java.util.Map;
+
+public interface CounterForOFPortBytesReceiveMBean {
+ //-----------
+ // operations
+ //-----------
+ public void setCounterDetails(Map<String, Integer> map);
+ public Map<String, Integer> getCounterDetails();
+ //-----------
+ // attributes
+ //-----------
+ public void invokePMManagedObjects(Map<String, Integer> map);
+ public Map<String, String> retrieveCounterMap();
+}
--- /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.pmcounters;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class CounterForOFPortBytesSent implements CounterForOFPortBytesSentMBean{
+
+ Map<String, Integer> counterCache = new HashMap<String, Integer>();
+ public static Map counterMap = new HashMap<String,String>();
+ public void invokePMManagedObjects(Map<String, Integer> map) {
+ setCounterDetails(map);
+ }
+
+ public Map<String, Integer> getCounterDetails() {
+ return counterCache;
+ }
+
+ public synchronized void setCounterDetails(Map<String, Integer> map) {
+ counterCache = map;
+ }
+
+ public Map<String, String> retrieveCounterMap(){
+ counterMap = (HashMap) counterCache;
+ return counterMap;
+ }
+
+}
\ 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.interfacemgr.pmcounters;
+
+import java.util.Map;
+
+public interface CounterForOFPortBytesSentMBean {
+ //-----------
+ // operations
+ //-----------
+ public void setCounterDetails(Map<String, Integer> map);
+ public Map<String, Integer> getCounterDetails();
+ //-----------
+ // attributes
+ //-----------
+ public void invokePMManagedObjects(Map<String, Integer> map);
+ public Map<String, String> retrieveCounterMap();
+}
--- /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.pmcounters;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class CounterForOFPortDuration implements CounterForOFPortDurationMBean{
+
+ Map<String, Integer> counterCache = new HashMap<String, Integer>();
+ public static Map counterMap = new HashMap<String,String>();
+ public void invokePMManagedObjects(Map<String, Integer> map) {
+ setCounterDetails(map);
+ }
+
+ public Map<String, Integer> getCounterDetails() {
+ return counterCache;
+ }
+
+ public synchronized void setCounterDetails(Map<String, Integer> map) {
+ counterCache = map;
+ }
+
+ public Map<String, String> retrieveCounterMap(){
+ counterMap = (HashMap) counterCache;
+ return counterMap;
+ }
+
+}
\ 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.interfacemgr.pmcounters;
+
+import java.util.Map;
+
+public interface CounterForOFPortDurationMBean {
+ //-----------
+ // operations
+ //-----------
+ public void setCounterDetails(Map<String, Integer> map);
+ public Map<String, Integer> getCounterDetails();
+ //-----------
+ // attributes
+ //-----------
+ public void invokePMManagedObjects(Map<String, Integer> map);
+ public Map<String, String> retrieveCounterMap();
+}
--- /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.pmcounters;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class CounterForOFPortPacketReceive implements CounterForOFPortPacketReceiveMBean{
+
+ Map<String, Integer> counterCache = new HashMap<String, Integer>();
+ public static Map counterMap = new HashMap<String,String>();
+ public void invokePMManagedObjects(Map<String, Integer> map) {
+ setCounterDetails(map);
+ }
+
+ public Map<String, Integer> getCounterDetails() {
+ return counterCache;
+ }
+
+ public synchronized void setCounterDetails(Map<String, Integer> map) {
+ counterCache = map;
+ }
+
+ public Map<String, String> retrieveCounterMap(){
+ counterMap = (HashMap) counterCache;
+ return counterMap;
+ }
+
+}
--- /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.pmcounters;
+
+import java.util.Map;
+
+public interface CounterForOFPortPacketReceiveMBean {
+ //-----------
+ // operations
+ //-----------
+ public void setCounterDetails(Map<String, Integer> map);
+ public Map<String, Integer> getCounterDetails();
+ //-----------
+ // attributes
+ //-----------
+ public void invokePMManagedObjects(Map<String, Integer> map);
+ public Map<String, String> retrieveCounterMap();
+}
--- /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.pmcounters;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class CounterForOFPortPacketSent implements CounterForOFPortPacketSentMBean{
+
+ Map<String, Integer> counterCache = new HashMap<String, Integer>();
+ public static Map counterMap = new HashMap<String,String>();
+ public void invokePMManagedObjects(Map<String, Integer> map) {
+ setCounterDetails(map);
+ }
+
+ public Map<String, Integer> getCounterDetails() {
+ return counterCache;
+ }
+
+ public synchronized void setCounterDetails(Map<String, Integer> map) {
+ counterCache = map;
+ }
+
+ public Map<String, String> retrieveCounterMap(){
+ counterMap = (HashMap) counterCache;
+ return counterMap;
+ }
+
+}
--- /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.pmcounters;
+
+import java.util.Map;
+
+public interface CounterForOFPortPacketSentMBean {
+ //-----------
+ // operations
+ //-----------
+ public void setCounterDetails(Map<String, Integer> map);
+ public Map<String, Integer> getCounterDetails();
+ //-----------
+ // attributes
+ //-----------
+ public void invokePMManagedObjects(Map<String, Integer> map);
+ public Map<String, String> retrieveCounterMap();
+}
\ 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.interfacemgr.pmcounters;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class CounterForOFPortReceiveDrop implements CounterForOFPortReceiveDropMBean{
+
+ Map<String, Integer> counterCache = new HashMap<String, Integer>();
+ public static Map counterMap = new HashMap<String,String>();
+ public void invokePMManagedObjects(Map<String, Integer> map) {
+ setCounterDetails(map);
+ }
+
+ public Map<String, Integer> getCounterDetails() {
+ return counterCache;
+ }
+
+ public synchronized void setCounterDetails(Map<String, Integer> map) {
+ counterCache = map;
+ }
+
+ public Map<String, String> retrieveCounterMap(){
+ counterMap = (HashMap) counterCache;
+ return counterMap;
+ }
+
+}
+
--- /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.pmcounters;
+
+import java.util.Map;
+
+public interface CounterForOFPortReceiveDropMBean {
+ //-----------
+ // operations
+ //-----------
+ public void setCounterDetails(Map<String, Integer> map);
+ public Map<String, Integer> getCounterDetails();
+ //-----------
+ // attributes
+ //-----------
+ public void invokePMManagedObjects(Map<String, Integer> map);
+ public Map<String, String> retrieveCounterMap();
+}
--- /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.pmcounters;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class CounterForOFPortReceiveError implements CounterForOFPortReceiveErrorMBean{
+
+ Map<String, Integer> counterCache = new HashMap<String, Integer>();
+ public static Map counterMap = new HashMap<String,String>();
+ public void invokePMManagedObjects(Map<String, Integer> map) {
+ setCounterDetails(map);
+ }
+
+ public Map<String, Integer> getCounterDetails() {
+ return counterCache;
+ }
+
+ public synchronized void setCounterDetails(Map<String, Integer> map) {
+ counterCache = map;
+ }
+
+ public Map<String, String> retrieveCounterMap(){
+ counterMap = (HashMap) counterCache;
+ return counterMap;
+ }
+
+}
+
--- /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.pmcounters;
+
+import java.util.Map;
+
+public interface CounterForOFPortReceiveErrorMBean {
+ //-----------
+ // operations
+ //-----------
+ public void setCounterDetails(Map<String, Integer> map);
+ public Map<String, Integer> getCounterDetails();
+ //-----------
+ // attributes
+ //-----------
+ public void invokePMManagedObjects(Map<String, Integer> map);
+ public Map<String, String> retrieveCounterMap();
+}
--- /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.pmcounters;
+
+import java.lang.Thread.UncaughtExceptionHandler;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+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.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.flow.table.statistics.rev131215.FlowTableStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.GetFlowTablesStatisticsInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.OpendaylightFlowTableStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.flow.table.and.statistics.map.FlowTableAndStatisticsMap;
+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.inventory.rev130819.NodeRef;
+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.port.statistics.rev131214.GetAllNodeConnectorsStatisticsInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.GetAllNodeConnectorsStatisticsInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.NodeConnectorStatisticsUpdate;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.OpendaylightPortStatisticsService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.port.statistics.rev131214.node.connector.statistics.and.port.number.map.NodeConnectorStatisticsAndPortNumberMap;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+
+public class NodeConnectorStatsImpl extends AbstractDataChangeListener<Node>{
+
+ private static final Logger logger = LoggerFactory.getLogger(NodeConnectorStatsImpl.class);
+ private static final int THREAD_POOL_SIZE = 4;
+ private static final int NO_DELAY = 0;
+ public static final PMAgentForNodeConnectorCounters pmagent = new PMAgentForNodeConnectorCounters();
+ private PortRpcStatisticsListener portStatsListener = new PortRpcStatisticsListener();
+ private FlowRpcStatisticsListener flowTableStatsListener = new FlowRpcStatisticsListener();
+ private List<BigInteger> nodes = new ArrayList<>();
+ Map<String, Map<String, String>> nodeAndNcIdOFPortDurationMap = new ConcurrentHashMap<String, Map<String, String>>();
+ Map<String, Map<String, String>> nodeAndNcIdOFPortReceiveDropMap = new ConcurrentHashMap<String, Map<String, String>>();
+ Map<String, Map<String, String>> nodeAndNcIdOFPortReceiveError = new ConcurrentHashMap<String, Map<String, String>>();
+ Map<String, Map<String, String>> nodeAndNcIdPacketSentMap = new ConcurrentHashMap<String, Map<String, String>>();
+ Map<String, Map<String, String>> nodeAndNcIdPacketReceiveMap = new ConcurrentHashMap<String, Map<String, String>>();
+ Map<String, Map<String, String>> nodeAndNcIdBytesSentMap = new ConcurrentHashMap<String, Map<String, String>>();
+ Map<String, Map<String, String>> nodeAndNcIdBytesReceiveMap = new ConcurrentHashMap<String, Map<String, String>>();
+ Map<String, Map<String, String>> nodeAndEntriesPerOFTableMap = new ConcurrentHashMap<String, Map<String, String>>();
+ private ScheduledFuture<?> scheduledResult;
+ private OpendaylightPortStatisticsService statPortService;
+ private ScheduledExecutorService portStatExecutorService;
+ private OpendaylightFlowTableStatisticsService opendaylightFlowTableStatisticsService;
+ public NodeConnectorStatsImpl(DataBroker db, NotificationService notificationService, OpendaylightPortStatisticsService statPortService, OpendaylightFlowTableStatisticsService opendaylightFlowTableStatisticsService) {
+ super(Node.class);
+ this.statPortService = statPortService;
+ this.opendaylightFlowTableStatisticsService = opendaylightFlowTableStatisticsService;
+ registerListener(db);
+ portStatExecutorService = Executors.newScheduledThreadPool(THREAD_POOL_SIZE, getThreadFactory("Port Stats Request Task"));
+ notificationService.registerNotificationListener(portStatsListener);
+ notificationService.registerNotificationListener(flowTableStatsListener);
+ pmagent.registerMbean();
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), NodeConnectorStatsImpl.this, AsyncDataBroker.DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ logger.error("NodeConnectorStatsImpl: DataChange listener registration fail!", e);
+ throw new IllegalStateException("NodeConnectorStatsImpl: registration Listener failed.", e);
+ }
+ }
+
+ private InstanceIdentifier<Node> getWildCardPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class);
+ }
+
+ /*
+ * PortStat request task is started when first DPN gets connected
+ */
+ private void schedulePortStatRequestTask() {
+ logger.info("Scheduling port statistics request");
+ PortStatRequestTask portStatRequestTask = new PortStatRequestTask();
+ scheduledResult = portStatExecutorService.scheduleAtFixedRate(portStatRequestTask, NO_DELAY, 10000, TimeUnit.MILLISECONDS);
+ }
+
+ /*
+ * PortStat request task is stopped when last DPN is removed.
+ */
+ private void stopPortStatRequestTask() {
+ if(scheduledResult != null) {
+ logger.info("Stopping port statistics request");
+ scheduledResult.cancel(true);
+ }
+ }
+
+ /*
+ * This task queries for node connector statistics as well as flowtables statistics every 10 secs.
+ * Minimum period which can be configured for PMJob is 10 secs.
+ */
+ private class PortStatRequestTask implements Runnable {
+
+ @Override
+ public void run() {
+ if(logger.isTraceEnabled()) {
+ logger.trace("Requesting port stats - {}");
+ }
+ for (BigInteger node : nodes) {
+ logger.trace("Requesting AllNodeConnectorStatistics for node - {}", node);
+ statPortService.getAllNodeConnectorsStatistics(buildGetAllNodeConnectorStatistics(node));
+ opendaylightFlowTableStatisticsService.getFlowTablesStatistics(buildGetFlowTablesStatistics(node));
+ }
+ }
+
+ private GetAllNodeConnectorsStatisticsInput buildGetAllNodeConnectorStatistics(BigInteger dpId) {
+ return new GetAllNodeConnectorsStatisticsInputBuilder()
+ .setNode(
+ new NodeRef(InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, new NodeKey(new NodeId("openflow:" + dpId.toString()))).build())).build();
+ }
+
+ private GetFlowTablesStatisticsInput buildGetFlowTablesStatistics(BigInteger dpId) {
+ return new GetFlowTablesStatisticsInputBuilder()
+ .setNode(
+ new NodeRef(InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, new NodeKey(new NodeId("openflow:" + dpId.toString()))).build())).build();
+ }
+
+ }
+
+ private ThreadFactory getThreadFactory(String threadNameFormat) {
+ ThreadFactoryBuilder builder = new ThreadFactoryBuilder();
+ builder.setNameFormat(threadNameFormat);
+ builder.setUncaughtExceptionHandler( new UncaughtExceptionHandler() {
+ @Override
+ public void uncaughtException(Thread t, Throwable e) {
+ logger.error("Received Uncaught Exception event in Thread: {}", t.getName(), e);
+ }
+ });
+ return builder.build();
+ }
+
+ /*
+ * PortRpcStatisticsListener listens for the NodeConnectorStatisticsUpdate and then update the corresponding counter map
+ */
+ class PortRpcStatisticsListener implements OpendaylightPortStatisticsListener {
+
+ @Override
+ public void onNodeConnectorStatisticsUpdate(NodeConnectorStatisticsUpdate ncStats) {
+ Map<String, String> ncIdOFPortDurationMap = new HashMap<String, String>();
+ Map<String, String> ncIdOFPortReceiveDropMap = new HashMap<String, String>();
+ Map<String, String> ncIdOFPortReceiveError = new HashMap<String, String>();
+ Map<String, String> ncIdPacketSentMap = new HashMap<String, String>();
+ Map<String, String> ncIdPacketReceiveMap = new HashMap<String, String>();
+ Map<String, String> ncIdBytesSentMap = new HashMap<String, String>();
+ Map<String, String> ncIdBytesReceiveMap = new HashMap<String, String>();
+ List<NodeConnectorStatisticsAndPortNumberMap> ncStatsAndPortMapList = ncStats.getNodeConnectorStatisticsAndPortNumberMap();
+ NodeId nodeId = ncStats.getId();
+ String node = nodeId.getValue().split(":")[1];
+ for (NodeConnectorStatisticsAndPortNumberMap ncStatsAndPortMap : ncStatsAndPortMapList) {
+ NodeConnectorId nodeConnector = ncStatsAndPortMap.getNodeConnectorId();
+ String port = nodeConnector.getValue().split(":")[2];
+ String nodePortStr = "dpnId_" + node + "_portNum_" + port;
+ ncIdOFPortDurationMap.put("OFPortDuration:" + nodePortStr + "_OFPortDuration", ncStatsAndPortMap.getDuration().getSecond().getValue().toString());
+ ncIdOFPortReceiveDropMap.put("PacketsPerOFPortReceiveDrop:" + nodePortStr + "_PacketsPerOFPortReceiveDrop", ncStatsAndPortMap.getReceiveDrops().toString());
+ ncIdOFPortReceiveError.put("PacketsPerOFPortReceiveError:" + nodePortStr + "_PacketsPerOFPortReceiveError", ncStatsAndPortMap.getReceiveErrors().toString());
+ ncIdPacketSentMap.put("PacketsPerOFPortSent:" + nodePortStr + "_PacketsPerOFPortSent", ncStatsAndPortMap.getPackets().getTransmitted().toString());
+ ncIdPacketReceiveMap.put("PacketsPerOFPortReceive:" + nodePortStr + "_PacketsPerOFPortReceive", ncStatsAndPortMap.getPackets().getReceived().toString());
+ ncIdBytesSentMap.put("BytesPerOFPortSent:" + nodePortStr + "_BytesPerOFPortSent", ncStatsAndPortMap.getBytes().getTransmitted().toString());
+ ncIdBytesReceiveMap.put("BytesPerOFPortReceive:" + nodePortStr + "_BytesPerOFPortReceive", ncStatsAndPortMap.getBytes().getReceived().toString());
+ }
+ logger.trace("Port Stats {}", ncStatsAndPortMapList);
+ //Storing allNodeConnectorStats(like ncIdOFPortDurationMap) in a map with key as node for easy removal and addition of allNodeConnectorStats.
+ nodeAndNcIdOFPortDurationMap.put(node, ncIdOFPortDurationMap);
+ nodeAndNcIdOFPortReceiveDropMap.put(node, ncIdOFPortReceiveDropMap);
+ nodeAndNcIdOFPortReceiveError.put(node, ncIdOFPortReceiveError);
+ nodeAndNcIdPacketSentMap.put(node, ncIdPacketSentMap);
+ nodeAndNcIdPacketReceiveMap.put(node, ncIdPacketReceiveMap);
+ nodeAndNcIdBytesSentMap.put(node, ncIdBytesSentMap);
+ nodeAndNcIdBytesReceiveMap.put(node, ncIdBytesReceiveMap);
+ //Combining the stats of all nodeconnectors in all nodes. This Map will be stored under MBean which will be queried as regular intervals.
+ ncIdOFPortDurationMap = combineAllNodesStats(nodeAndNcIdOFPortDurationMap);
+ ncIdOFPortReceiveDropMap = combineAllNodesStats(nodeAndNcIdOFPortReceiveDropMap);
+ ncIdOFPortReceiveError = combineAllNodesStats(nodeAndNcIdOFPortReceiveError);
+ ncIdPacketSentMap = combineAllNodesStats(nodeAndNcIdPacketSentMap);
+ ncIdPacketReceiveMap = combineAllNodesStats(nodeAndNcIdPacketReceiveMap);
+ ncIdBytesSentMap = combineAllNodesStats(nodeAndNcIdBytesSentMap);
+ ncIdBytesReceiveMap = combineAllNodesStats(nodeAndNcIdBytesReceiveMap);
+ pmagent.connectToPMAgent(ncIdOFPortDurationMap, ncIdOFPortReceiveDropMap, ncIdOFPortReceiveError, ncIdPacketSentMap, ncIdPacketReceiveMap, ncIdBytesSentMap, ncIdBytesReceiveMap);
+ }
+
+ /*
+ * Input allNodesStats contains statistics of all nodeConnectors of all nodes. Key is the node and values contains another map with key as node connector and value as statresult.
+ * Output will be a map with key as nodeconnector and value as the statresult. The key contains nodeconnectors of all the nodes.
+ */
+ }
+
+ private Map<String, String> combineAllNodesStats(Map<String, Map<String, String>> allNodesStats) {
+ Map<String, String> allNcsStatsMap = new HashMap<String, String>();
+ for (Map.Entry<String, Map<String, String>> entry : allNodesStats.entrySet()) {
+ Map<String, String> ncStatsMap = entry.getValue();
+ for (Map.Entry<String, String> statResult : ncStatsMap.entrySet()) {
+ allNcsStatsMap.put(statResult.getKey(), statResult.getValue());
+ }
+ }
+ return allNcsStatsMap;
+ }
+
+ /*
+ * FlowRpcStatisticsListener listens for the FlowTableStatisticsUpdate and then update the corresponding counter map
+ */
+ class FlowRpcStatisticsListener implements OpendaylightFlowTableStatisticsListener {
+
+ @Override
+ public void onFlowTableStatisticsUpdate(FlowTableStatisticsUpdate flowTableStats) {
+ String node = flowTableStats.getId().getValue().split(":")[1];
+ Map<String, String> entriesPerOFTableMap = new HashMap<String, String>();
+ List<FlowTableAndStatisticsMap> flowTableAndStatisticsMapList = flowTableStats.getFlowTableAndStatisticsMap();
+ for (FlowTableAndStatisticsMap flowTableAndStatisticsMap : flowTableAndStatisticsMapList) {
+ String nodeTableStr = "dpnId_" + node + "_table_" + flowTableAndStatisticsMap.getTableId().getValue().toString();
+ entriesPerOFTableMap.put("EntriesPerOFTable:" + nodeTableStr + "_EntriesPerOFTable", flowTableAndStatisticsMap.getActiveFlows().getValue().toString());
+ }
+ nodeAndEntriesPerOFTableMap.put(node, entriesPerOFTableMap);
+ entriesPerOFTableMap = combineAllNodesStats(nodeAndEntriesPerOFTableMap);
+ pmagent.connectToPMAgentAndInvokeEntriesPerOFTable(entriesPerOFTableMap);
+ }
+
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Node> identifier, Node node) {
+ NodeId nodeId = node.getId();
+ String nodeVal = nodeId.getValue().split(":")[1];
+ BigInteger dpId = new BigInteger(nodeVal);
+ if (nodes.contains(dpId)) {
+ nodes.remove(dpId);
+ nodeAndNcIdOFPortDurationMap.remove(nodeVal);
+ nodeAndNcIdOFPortReceiveDropMap.remove(nodeVal);
+ nodeAndNcIdOFPortReceiveError.remove(nodeVal);
+ nodeAndNcIdPacketSentMap.remove(nodeVal);
+ nodeAndNcIdPacketReceiveMap.remove(nodeVal);
+ nodeAndNcIdBytesSentMap.remove(nodeVal);
+ nodeAndNcIdBytesReceiveMap.remove(nodeVal);
+ nodeAndEntriesPerOFTableMap.remove(nodeVal);
+ }
+ if (nodes.isEmpty()) {
+ stopPortStatRequestTask();
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Node> identifier, Node original,
+ Node update) {
+ // TODO Auto-generated method stub
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Node> identifier, Node node) {
+ NodeId nodeId = node.getId();
+ BigInteger dpId = new BigInteger(nodeId.getValue().split(":")[1]);
+ if (nodes.contains(dpId)) {
+ return;
+ }
+ nodes.add(dpId);
+ if (nodes.size() == 1) {
+ schedulePortStatRequestTask();
+ }
+ }
+}
--- /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.pmcounters;
+
+import java.lang.management.ManagementFactory;
+import java.util.Map;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PMAgentForNodeConnectorCounters {
+
+ private static Logger logger = LoggerFactory.getLogger(PMAgentForNodeConnectorCounters.class);
+ private MBeanServer mbServer = null;
+ private ObjectName mbeanForOFPortDuration = null;
+ private ObjectName mbeanForOFPortReceiveDrop = null;
+ private ObjectName mbeanForOFPortReceiveError = null;
+ private ObjectName mbeanForOFPortPacketSent = null;
+ private ObjectName mbeanForOFPortPacketReceive = null;
+ private ObjectName mbeanForOFPortBytesSent = null;
+ private ObjectName mbeanForOFPortBytesReceive = null;
+ private ObjectName mbeanForEntriesPerOFTable = null;
+ private static final String BEANNAMEFOROFPORTDURATION = "SDNC.PM:type=CounterForOFPortDuration";
+ private static final String BEANNAMEFOROFPORTREVEIVEDROP = "SDNC.PM:type=CounterForOFPortReceiveDrop";
+ private static final String BEANNAMEFOROFPORTREVEIVEERROR = "SDNC.PM:type=CounterForOFPortReceiveError";
+ private static final String BEANNAMEFOROFPORTPACKETSENT = "SDNC.PM:type=CounterForOFPortPacketSent";
+ private static final String BEANNAMEFOROFPORTPACKETRECEIVE = "SDNC.PM:type=CounterForOFPortPacketReceive";
+ private static final String BEANNAMEFOROFPORTBYTESSENT = "SDNC.PM:type=CounterForOFPortBytesSent";
+ private static final String BEANNAMEFOROFPORTBYTESRECEIVE = "SDNC.PM:type=CounterForOFPortBytesReceive";
+ private static final String BEANNAMEFORENTRIESPEROFTABLE = "SDNC.PM:type=CounterForEntriesPerOFTable";
+ private static CounterForOFPortDuration counterForOFPortDurationBean = new CounterForOFPortDuration();
+ private static CounterForOFPortReceiveDrop counterForOFPortReceiveDropBean = new CounterForOFPortReceiveDrop();
+ private static CounterForOFPortReceiveError counterForOFPortReceiveErrorBean = new CounterForOFPortReceiveError();
+ private static CounterForOFPortPacketSent counterForOFPortPacketSent = new CounterForOFPortPacketSent();
+ private static CounterForOFPortPacketReceive counterForOFPortPacketReceive = new CounterForOFPortPacketReceive();
+ private static CounterForOFPortBytesSent counterForOFPortBytesSent = new CounterForOFPortBytesSent();
+ private static CounterForOFPortBytesReceive counterForOFPortBytesReceive = new CounterForOFPortBytesReceive();
+ private static CounterForEntriesPerOFTable counterForEntriesPerOFTable = new CounterForEntriesPerOFTable();
+
+ public PMAgentForNodeConnectorCounters() {
+ // Get the platform MBeanServer
+ mbServer = ManagementFactory.getPlatformMBeanServer();
+ try {
+ mbeanForOFPortDuration = new ObjectName(BEANNAMEFOROFPORTDURATION);
+ mbeanForOFPortReceiveDrop = new ObjectName(BEANNAMEFOROFPORTREVEIVEDROP);
+ mbeanForOFPortReceiveError = new ObjectName(BEANNAMEFOROFPORTREVEIVEERROR);
+ mbeanForOFPortPacketSent = new ObjectName(BEANNAMEFOROFPORTPACKETSENT);
+ mbeanForOFPortPacketReceive = new ObjectName(BEANNAMEFOROFPORTPACKETRECEIVE);
+ mbeanForOFPortBytesSent = new ObjectName(BEANNAMEFOROFPORTBYTESSENT);
+ mbeanForOFPortBytesReceive = new ObjectName(BEANNAMEFOROFPORTBYTESRECEIVE);
+ mbeanForEntriesPerOFTable = new ObjectName(BEANNAMEFORENTRIESPEROFTABLE);
+ } catch (MalformedObjectNameException e) {
+ logger.error("ObjectName instance creation failed with exception {}", e);
+
+ }
+ }
+
+ public void registerMbean() {
+ try {
+ // Uniquely identify the MBeans and register them with the platform MBeanServer
+ if(!mbServer.isRegistered(mbeanForOFPortDuration)) {
+ mbServer.registerMBean(counterForOFPortDurationBean, mbeanForOFPortDuration);
+ logger.info("Registered Mbean {} successfully", mbeanForOFPortDuration);
+ }
+ if(!mbServer.isRegistered(mbeanForOFPortReceiveDrop)) {
+ mbServer.registerMBean(counterForOFPortReceiveDropBean, mbeanForOFPortReceiveDrop);
+ logger.info("Registered Mbean {} successfully", mbeanForOFPortReceiveDrop);
+ }
+ if(!mbServer.isRegistered(mbeanForOFPortReceiveError)) {
+ mbServer.registerMBean(counterForOFPortReceiveErrorBean, mbeanForOFPortReceiveError);
+ logger.info("Registered Mbean {} successfully", mbeanForOFPortReceiveError);
+ }
+ if(!mbServer.isRegistered(mbeanForOFPortPacketSent)) {
+ mbServer.registerMBean(counterForOFPortPacketSent, mbeanForOFPortPacketSent);
+ logger.info("Registered Mbean {} successfully", mbeanForOFPortPacketSent);
+ }
+ if(!mbServer.isRegistered(mbeanForOFPortPacketReceive)) {
+ mbServer.registerMBean(counterForOFPortPacketReceive, mbeanForOFPortPacketReceive);
+ logger.info("Registered Mbean {} successfully", mbeanForOFPortPacketReceive);
+ }
+ if(!mbServer.isRegistered(mbeanForOFPortBytesSent)) {
+ mbServer.registerMBean(counterForOFPortBytesSent, mbeanForOFPortBytesSent);
+ logger.info("Registered Mbean {} successfully", mbeanForOFPortBytesSent);
+ }
+ if(!mbServer.isRegistered(mbeanForOFPortBytesReceive)) {
+ mbServer.registerMBean(counterForOFPortBytesReceive, mbeanForOFPortBytesReceive);
+ logger.info("Registered Mbean {} successfully", mbeanForOFPortBytesReceive);
+ }
+ if(!mbServer.isRegistered(mbeanForEntriesPerOFTable)) {
+ mbServer.registerMBean(counterForEntriesPerOFTable, mbeanForEntriesPerOFTable);
+ logger.info("Registered Mbean {} successfully", mbeanForEntriesPerOFTable);
+ }
+ } catch(Exception e) {
+ logger.error("Registeration failed with exception {}", e);
+ }
+ }
+
+
+ public synchronized void connectToPMAgent(Map<String, String> ofPortDurationCounter, Map<String, String> ofPortReceiveDropCounter,
+ Map<String, String> ofPortReceiveErrorCounter, Map<String, String> ofPortPacketSent, Map<String, String> ofPortPacketReceive,
+ Map<String, String> ofPortBytesSent, Map<String, String> ofPortBytesReceive) {
+ try {
+ mbServer.invoke(mbeanForOFPortDuration, "invokePMManagedObjects", new Object[]{ofPortDurationCounter}, new String[]{Map.class.getName()});
+ mbServer.invoke(mbeanForOFPortReceiveDrop, "invokePMManagedObjects", new Object[]{ofPortReceiveDropCounter}, new String[]{Map.class.getName()});
+ mbServer.invoke(mbeanForOFPortReceiveError, "invokePMManagedObjects", new Object[]{ofPortReceiveErrorCounter}, new String[]{Map.class.getName()});
+ mbServer.invoke(mbeanForOFPortPacketSent, "invokePMManagedObjects", new Object[]{ofPortPacketSent}, new String[]{Map.class.getName()});
+ mbServer.invoke(mbeanForOFPortPacketReceive, "invokePMManagedObjects", new Object[]{ofPortPacketReceive}, new String[]{Map.class.getName()});
+ mbServer.invoke(mbeanForOFPortBytesSent, "invokePMManagedObjects", new Object[]{ofPortBytesSent}, new String[]{Map.class.getName()});
+ mbServer.invoke(mbeanForOFPortBytesReceive, "invokePMManagedObjects", new Object[]{ofPortBytesReceive}, new String[]{Map.class.getName()});
+ } catch (InstanceNotFoundException e ) {
+ logger.error(" InstanceNotFoundException ", e);
+ } catch (MBeanException e) {
+ logger.error(" MBeanException ", e);
+ } catch (ReflectionException e) {
+ logger.error(" ReflectionException ", e);
+ }
+ }
+
+ public synchronized void connectToPMAgentAndInvokeEntriesPerOFTable(Map<String, String> entriesPerOFTable) {
+ try {
+ mbServer.invoke(mbeanForEntriesPerOFTable, "invokePMManagedObjects", new Object[]{entriesPerOFTable}, new String[]{Map.class.getName()});
+ } catch (InstanceNotFoundException e ) {
+ logger.error(" InstanceNotFoundException ", e);
+ } catch (MBeanException e) {
+ logger.error(" MBeanException ", e);
+ } catch (ReflectionException e) {
+ logger.error(" ReflectionException ", e);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.confighelpers;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.utilities.SouthboundUtils;
+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.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.Tunnels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class HwVTEPConfigRemoveHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(HwVTEPConfigRemoveHelper.class);
+
+ public static List<ListenableFuture<Void>> removeConfiguration(DataBroker dataBroker, Interface interfaceOld,
+ InstanceIdentifier<Node> globalNodeId,
+ InstanceIdentifier<Node> physicalSwitchNodeId) {
+ List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+ LOG.info("removing hwvtep configuration for {}", interfaceOld.getName());
+ if(globalNodeId != null) {
+ IfTunnel ifTunnel = interfaceOld.getAugmentation(IfTunnel.class);
+ //removeTunnelTableEntry(transaction, ifTunnel, physicalSwitchNodeId);
+ removeTerminationEndPoint(transaction, ifTunnel, globalNodeId);
+ InterfaceManagerCommonUtils.deleteStateEntry(interfaceOld.getName(), transaction);
+ InterfaceMetaUtils.removeTunnelToInterfaceMap(physicalSwitchNodeId, transaction, ifTunnel);
+ }
+ futures.add(transaction.submit());
+ return futures;
+ }
+
+ private static void removeTerminationEndPoint(WriteTransaction transaction, IfTunnel ifTunnel,
+ InstanceIdentifier<Node> globalNodeId) {
+ LOG.info("removing remote termination end point {}", ifTunnel.getTunnelDestination());
+ TerminationPointKey tpKey = SouthboundUtils.getTerminationPointKey(ifTunnel.getTunnelDestination().
+ getIpv4Address().getValue());
+ InstanceIdentifier<TerminationPoint> tpPath = SouthboundUtils.createInstanceIdentifier
+ (globalNodeId, tpKey);
+ transaction.delete(LogicalDatastoreType.CONFIGURATION, tpPath);
+ }
+
+ private static void removeTunnelTableEntry(WriteTransaction transaction, IfTunnel ifTunnel,
+ InstanceIdentifier<Node> physicalSwitchNodeId) {
+ LOG.info("removing tunnel table entry for {}", ifTunnel.getTunnelDestination());
+ InstanceIdentifier<Tunnels> tunnelsInstanceIdentifier = SouthboundUtils.createTunnelsInstanceIdentifier(physicalSwitchNodeId,
+ ifTunnel.getTunnelSource(), ifTunnel.getTunnelDestination());
+ transaction.delete(LogicalDatastoreType.CONFIGURATION, tunnelsInstanceIdentifier);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.confighelpers;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.utilities.SouthboundUtils;
+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.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeVxlanOverIpv4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class HwVTEPInterfaceConfigAddHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(HwVTEPInterfaceConfigAddHelper.class);
+
+ public static List<ListenableFuture<Void>> addConfiguration(DataBroker dataBroker, InstanceIdentifier<Node> physicalSwitchNodeId,
+ InstanceIdentifier<Node> globalNodeId,
+ Interface interfaceNew, IfTunnel ifTunnel) {
+ List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
+ LOG.info("adding hwvtep configuration for {}", interfaceNew.getName());
+
+ // create hwvtep through ovsdb plugin
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+ InterfaceMetaUtils.createTunnelToInterfaceMap(interfaceNew.getName(), physicalSwitchNodeId, transaction, ifTunnel);
+ if(globalNodeId != null) {
+ addTerminationPoints(transaction, futures, globalNodeId,ifTunnel);
+ SouthboundUtils.addStateEntry(interfaceNew, interfaceNew.getAugmentation(IfTunnel.class), transaction);
+ }else{
+ LOG.debug("specified physical switch is not connected {}", physicalSwitchNodeId);
+ }
+ futures.add(transaction.submit());
+ return futures;
+ }
+
+ /*
+ * For each hwvtep configuration, we need to configure Physical LocatorTable of hwvtep schema with
+ * destination IP and tunnel-type. The configuration needs to be done for both local endpoint as well as remote endpoint
+ */
+ public static void addTerminationPoints(WriteTransaction transaction,
+ List<ListenableFuture<Void>> futures,
+ InstanceIdentifier<Node> globalNodeId,
+ IfTunnel ifTunnel) {
+ //InstanceIdentifier<TerminationPoint> localTEP =
+ // createLocalPhysicalLocatorEntryIfNotPresent(futures, dataBroker,transaction, ifTunnel, globalNodeId);
+ createRemotePhysicalLocatorEntry(transaction, futures, globalNodeId, ifTunnel.getTunnelDestination());
+ //InstanceIdentifier<Tunnels> tunnelsInstanceIdentifier = createTunnelTableEntry(transaction, physicalSwitchNodeId, localTEP, remoteTEP);
+ }
+
+ private static InstanceIdentifier<TerminationPoint> createRemotePhysicalLocatorEntry(WriteTransaction transaction, List<ListenableFuture<Void>> futures,
+ InstanceIdentifier<Node> nodeIid, IpAddress destIPAddress){
+ String remoteIp = destIPAddress.getIpv4Address().getValue();
+ LOG.debug("creating remote physical locator entry {}", remoteIp);
+ TerminationPointKey tpKey = SouthboundUtils.getTerminationPointKey(remoteIp);
+ InstanceIdentifier<TerminationPoint> tpPath =
+ SouthboundUtils.createInstanceIdentifier(nodeIid, tpKey);
+ createPhysicalLocatorEntry(transaction, futures, tpPath, tpKey, destIPAddress);
+ return tpPath;
+ }
+
+ /*
+ * This method writes the termination end point details to the topology Config DS
+ */
+ private static void createPhysicalLocatorEntry(WriteTransaction transaction, List<ListenableFuture<Void>> futures,
+ InstanceIdentifier<TerminationPoint> tpPath, TerminationPointKey terminationPointKey,
+ IpAddress destIPAddress){
+ TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
+ HwvtepPhysicalLocatorAugmentationBuilder tpAugmentationBuilder =
+ new HwvtepPhysicalLocatorAugmentationBuilder();
+ tpBuilder.setKey(terminationPointKey);
+ tpBuilder.setTpId(terminationPointKey.getTpId());
+ tpAugmentationBuilder.setEncapsulationType(EncapsulationTypeVxlanOverIpv4.class);
+ SouthboundUtils.setDstIp(tpAugmentationBuilder, destIPAddress);
+ tpBuilder.addAugmentation(HwvtepPhysicalLocatorAugmentation.class, tpAugmentationBuilder.build());
+ LOG.debug("creating physical locator entry for {}", terminationPointKey);
+ transaction.put(LogicalDatastoreType.CONFIGURATION,
+ tpPath, tpBuilder.build(), 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.interfacemgr.renderer.hwvtep.confighelpers;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.utilities.SouthboundUtils;
+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.opendaylight.params.xml.ns.yang.overlay.rev150105.Tunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeVxlanOverIpv4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.Tunnels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.tunnel.attributes.BfdParams;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class HwVTEPInterfaceConfigUpdateHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(HwVTEPInterfaceConfigUpdateHelper.class);
+
+ public static List<ListenableFuture<Void>> updateConfiguration(DataBroker dataBroker, InstanceIdentifier<Node> physicalSwitchNodeId,
+ InstanceIdentifier<Node> globalNodeId,
+ Interface interfaceNew, IfTunnel ifTunnel) {
+ List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
+ LOG.info("adding hwvtep configuration for {}", interfaceNew.getName());
+
+ // create hwvtep through ovsdb plugin
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+ if(globalNodeId != null) {
+ updateBfdMonitoring(dataBroker, globalNodeId, physicalSwitchNodeId, ifTunnel);
+
+ }else{
+ LOG.debug("specified physical switch is not connected {}", physicalSwitchNodeId);
+ }
+ futures.add(transaction.submit());
+ return futures;
+ }
+
+ /*
+ * bfd monitoring interval and enable/disbale attributes can be modified
+ */
+ public static List<ListenableFuture<Void>> updateBfdMonitoring(DataBroker dataBroker, InstanceIdentifier<Node> globalNodeId, InstanceIdentifier<Node> physicalSwitchId,
+ IfTunnel ifTunnel) {
+ List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+ TunnelsBuilder tBuilder = new TunnelsBuilder();
+ InstanceIdentifier<TerminationPoint> localTEPInstanceIdentifier =
+ SouthboundUtils.createTEPInstanceIdentifier(globalNodeId, ifTunnel.getTunnelSource());
+ InstanceIdentifier<TerminationPoint> remoteTEPInstanceIdentifier =
+ SouthboundUtils.createTEPInstanceIdentifier(globalNodeId, ifTunnel.getTunnelDestination());
+ InstanceIdentifier<Tunnels> tunnelsInstanceIdentifier = SouthboundUtils.
+ createTunnelsInstanceIdentifier(physicalSwitchId, localTEPInstanceIdentifier, remoteTEPInstanceIdentifier);
+
+ LOG.debug("updating bfd monitoring parameters for the hwvtep {}", tunnelsInstanceIdentifier);
+ tBuilder.setKey(new TunnelsKey(new HwvtepPhysicalLocatorRef(localTEPInstanceIdentifier),
+ new HwvtepPhysicalLocatorRef(remoteTEPInstanceIdentifier)));
+ List <BfdParams> bfdParams = new ArrayList<>();
+ SouthboundUtils.fillBfdParameters(bfdParams, ifTunnel);
+ tBuilder.setBfdParams(bfdParams);
+ transaction.merge(LogicalDatastoreType.CONFIGURATION, tunnelsInstanceIdentifier,tBuilder.build(), true);
+ futures.add(transaction.submit());
+ return futures;
+ }
+}
--- /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.renderer.hwvtep.statehelpers;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.Tunnels;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class HwVTEPInterfaceStateRemoveHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(HwVTEPInterfaceStateRemoveHelper.class);
+
+ public static List<ListenableFuture<Void>> removeExternalTunnel(DataBroker dataBroker,
+ InstanceIdentifier<Tunnels> tunnelsInstanceIdentifier) {
+ List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
+ LOG.debug("Removing HwVTEP tunnel entries for tunnel: {}", tunnelsInstanceIdentifier);
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+ transaction.delete(LogicalDatastoreType.CONFIGURATION, tunnelsInstanceIdentifier);
+ futures.add(transaction.submit());
+ return futures;
+ }
+}
--- /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.renderer.hwvtep.statehelpers;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.utilities.SouthboundUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.Tunnels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.tunnel.attributes.BfdParams;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.tunnel.attributes.BfdStatus;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class HwVTEPInterfaceStateUpdateHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(HwVTEPInterfaceStateUpdateHelper.class);
+
+ public static List<ListenableFuture<Void>> updatePhysicalSwitch(DataBroker dataBroker, InstanceIdentifier<Tunnels> tunnelsInstanceIdentifier,
+ Tunnels tunnelsNew, Tunnels tunnelsOld) {
+ List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
+ LOG.debug("updating physical switch for tunnels");
+ String interfaceName =
+ InterfaceMetaUtils.getInterfaceForTunnelInstanceIdentifier(tunnelsInstanceIdentifier.toString(), dataBroker);
+ if (interfaceName == null) {
+ return futures;
+ }
+
+ // update opstate of interface if TEP has gone down/up as a result of BFD monitoring
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+ InterfaceManagerCommonUtils.updateOpState(transaction, interfaceName, getTunnelOpState(tunnelsNew.getBfdStatus()));
+ futures.add(transaction.submit());
+ return futures;
+ }
+
+ private static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus
+ getTunnelOpState(List<BfdStatus> tunnelBfdStatus) {
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus
+ livenessState = org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
+ if (tunnelBfdStatus != null && !tunnelBfdStatus.isEmpty()) {
+ for (BfdStatus bfdState : tunnelBfdStatus) {
+ if (bfdState.getBfdStatusKey().equalsIgnoreCase(SouthboundUtils.BFD_OP_STATE)) {
+ String bfdOpState = bfdState.getBfdStatusValue();
+ if (bfdOpState.equalsIgnoreCase(SouthboundUtils.BFD_STATE_UP)) {
+ livenessState = org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Up;
+ } else {
+ livenessState = org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
+ }
+ break;
+ }
+ }
+ }
+ return livenessState;
+ }
+
+
+ public static List<ListenableFuture<Void>> startBfdMonitoring(DataBroker dataBroker,
+ InstanceIdentifier<Tunnels> tunnelsInstanceIdentifier,
+ Tunnels tunnelsNew) {
+ List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
+ /*String interfaceName =
+ InterfaceMetaUtils.getInterfaceForTunnelInstanceIdentifier(tunnelsInstanceIdentifier.toString(), dataBroker);
+ if (interfaceName == null) {
+ LOG.debug("no interface configured for the tunnel {}", tunnelsInstanceIdentifier);
+ return futures;
+ }*/
+
+ LOG.debug("starting bfd monitoring for the hwvtep {}", tunnelsInstanceIdentifier);
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+ TunnelsBuilder tBuilder = new TunnelsBuilder();
+ tBuilder.setKey(new TunnelsKey(tunnelsNew.getLocalLocatorRef(), tunnelsNew.getRemoteLocatorRef()));
+ tBuilder.setLocalLocatorRef(tunnelsNew.getLocalLocatorRef());
+ tBuilder.setRemoteLocatorRef(tunnelsNew.getLocalLocatorRef());
+ List <BfdParams> bfdParams = new ArrayList<>();
+ SouthboundUtils.fillBfdParameters(bfdParams, null);
+ tBuilder.setBfdParams(bfdParams);
+ transaction.put(LogicalDatastoreType.CONFIGURATION, tunnelsInstanceIdentifier,tBuilder.build(), true);
+ futures.add(transaction.submit());
+ return futures;
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.utilities;
+
+import com.google.common.base.Optional;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+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.inet.types.rev100924.Uri;
+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.state.InterfaceBuilder;
+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.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeVxlanOverIpv4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.Tunnels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.tunnel.attributes.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.monitor.profiles.MonitorProfile;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SouthboundUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(SouthboundUtils.class);
+ public static final String HWVTEP_TOPOLOGY = "hwvtep:1";
+ public static final TopologyId HWVTEP_TOPOLOGY_ID = new TopologyId(new Uri(HWVTEP_TOPOLOGY));
+ public static final String TEP_PREFIX = "vxlan_over_ipv4:";
+ public static final String BFD_OP_STATE = "state";
+ public static final String BFD_STATE_UP = "up";
+ // BFD parameters
+ static final String BFD_PARAM_ENABLE = "enable";
+ static final String BFD_PARAM_MIN_RX = "min_rx";
+ static final String BFD_PARAM_MIN_TX = "min_tx";
+ static final String BFD_PARAM_DECAY_MIN_RX = "decay_min_rx";
+ static final String BFD_PARAM_FORWARDING_IF_RX = "forwarding_if_rx";
+ static final String BFD_PARAM_CPATH_DOWN = "cpath_down";
+ static final String BFD_PARAM_CHECK_TNL_KEY = "check_tnl_key";
+
+ // BFD Local/Remote Configuration parameters
+ static final String BFD_CONFIG_BFD_DST_MAC = "bfd_dst_mac";
+ static final String BFD_CONFIG_BFD_DST_IP = "bfd_dst_ip";
+
+ // bfd params
+ private static final String BFD_MIN_RX_VAL = "1000";
+ private static final String BFD_MIN_TX_VAL = "100";
+ private static final String BFD_DECAY_MIN_RX_VAL = "200";
+ private static final String BFD_FORWARDING_IF_RX_VAL = "true";
+ private static final String BFD_CPATH_DOWN_VAL = "false";
+ private static final String BFD_CHECK_TNL_KEY_VAL = "false";
+
+ public static InstanceIdentifier<Node> createPhysicalSwitchInstanceIdentifier(String psNodeIdString) {
+ NodeId physicalSwitchNodeId = new NodeId(psNodeIdString);
+ InstanceIdentifier<Node> psNodeId = InstanceIdentifier
+ .create(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(HWVTEP_TOPOLOGY_ID))
+ .child(Node.class,new NodeKey(physicalSwitchNodeId));
+ return psNodeId;
+ }
+
+ public static InstanceIdentifier<Node> createGlobalNodeInstanceIdentifier(DataBroker dataBroker, String physicalSwitchNodeId) {
+ InstanceIdentifier<Node> psNodeId = InstanceIdentifier
+ .create(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(HWVTEP_TOPOLOGY_ID))
+ .child(Node.class,new NodeKey(new NodeId(physicalSwitchNodeId)));
+ Optional<Node> physicalSwitchOptional =
+ IfmUtil.read(LogicalDatastoreType.OPERATIONAL, psNodeId, dataBroker);
+ if (!physicalSwitchOptional.isPresent()) {
+ LOG.debug("physical switch is not present for {}", physicalSwitchNodeId);
+ return null;
+ }
+ Node physicalSwitch = physicalSwitchOptional.get();
+ PhysicalSwitchAugmentation physicalSwitchAugmentation = physicalSwitch.getAugmentation(PhysicalSwitchAugmentation.class);
+ return (InstanceIdentifier<Node>) physicalSwitchAugmentation.getManagedBy().getValue();
+ }
+
+ public static InstanceIdentifier<TerminationPoint> createTEPInstanceIdentifier
+ (InstanceIdentifier<Node> nodeIid, IpAddress ipAddress) {
+ TerminationPointKey localTEP = SouthboundUtils.getTerminationPointKey(ipAddress.getIpv4Address().getValue());
+ return createInstanceIdentifier(nodeIid, localTEP);
+ }
+
+ public static InstanceIdentifier<TerminationPoint> createInstanceIdentifier(InstanceIdentifier<Node> nodeIid,
+ TerminationPointKey tpKey) {
+ return nodeIid.child(TerminationPoint.class, tpKey);
+ }
+
+ public static InstanceIdentifier<Tunnels> createTunnelsInstanceIdentifier(InstanceIdentifier<Node> nodeId, IpAddress localIP, IpAddress remoteIp) {
+ InstanceIdentifier<TerminationPoint> localTEPInstanceIdentifier =
+ createTEPInstanceIdentifier(nodeId, localIP);
+ InstanceIdentifier<TerminationPoint> remoteTEPInstanceIdentifier =
+ createTEPInstanceIdentifier(nodeId, remoteIp);
+
+ TunnelsKey tunnelsKey = new TunnelsKey(new HwvtepPhysicalLocatorRef(localTEPInstanceIdentifier),
+ new HwvtepPhysicalLocatorRef(remoteTEPInstanceIdentifier));
+ return InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class, new TopologyKey(HWVTEP_TOPOLOGY_ID))
+ .child(Node.class, new NodeKey(nodeId.firstKeyOf(Node.class))).augmentation(PhysicalSwitchAugmentation.class)
+ .child(Tunnels.class, tunnelsKey).build();
+ }
+
+ public static InstanceIdentifier<Tunnels> createTunnelsInstanceIdentifier(InstanceIdentifier<Node> nodeId,
+ InstanceIdentifier<TerminationPoint> localTEPInstanceIdentifier,
+ InstanceIdentifier<TerminationPoint> remoteTEPInstanceIdentifier) {
+ TunnelsKey tunnelsKey = new TunnelsKey(new HwvtepPhysicalLocatorRef(localTEPInstanceIdentifier),
+ new HwvtepPhysicalLocatorRef(remoteTEPInstanceIdentifier));
+
+ InstanceIdentifier<Tunnels> tunnelInstanceId = InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class, new TopologyKey(HWVTEP_TOPOLOGY_ID))
+ .child(Node.class, new NodeKey(nodeId.firstKeyOf(Node.class))).augmentation(PhysicalSwitchAugmentation.class)
+ .child(Tunnels.class, tunnelsKey).build();
+ return tunnelInstanceId;
+ }
+
+ public static String getTerminationPointKeyString(String ipAddress) {
+ String tpKeyStr = null;
+ if(ipAddress != null) {
+ tpKeyStr = new StringBuilder(TEP_PREFIX).
+ append(ipAddress).toString();
+ }
+ return tpKeyStr;
+ }
+
+ public static TerminationPointKey getTerminationPointKey(String ipAddress) {
+ TerminationPointKey tpKey = null;
+ String tpKeyStr = getTerminationPointKeyString(ipAddress);
+ if(tpKeyStr != null) {
+ tpKey = new TerminationPointKey(new TpId(tpKeyStr));
+ }
+ return tpKey;
+ }
+
+ public static void setDstIp(HwvtepPhysicalLocatorAugmentationBuilder tpAugmentationBuilder, IpAddress ipAddress) {
+ IpAddress ip = new IpAddress(ipAddress);
+ tpAugmentationBuilder.setDstIp(ip);
+ }
+
+ public static void addStateEntry(Interface interfaceInfo, IfTunnel ifTunnel, WriteTransaction transaction) {
+ LOG.debug("adding tep interface state for {}", interfaceInfo.getName());
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus operStatus =
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Up;
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus adminStatus =
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus.Up;
+ if (interfaceInfo != null && !interfaceInfo.isEnabled()) {
+ operStatus = org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
+ }
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
+ IfmUtil.buildStateInterfaceId(interfaceInfo.getName());
+ List<String> childLowerLayerIfList = new ArrayList<>();
+ childLowerLayerIfList.add(0, SouthboundUtils.getTerminationPointKeyString(ifTunnel.getTunnelDestination().getIpv4Address().getValue()));
+ InterfaceBuilder ifaceBuilder = new InterfaceBuilder().setAdminStatus(adminStatus)
+ .setOperStatus(operStatus).setLowerLayerIf(childLowerLayerIfList);
+
+
+ if(interfaceInfo != null){
+ ifaceBuilder.setType(interfaceInfo.getType());
+ }
+ ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(interfaceInfo.getName()));
+ transaction.put(LogicalDatastoreType.OPERATIONAL, ifStateId,ifaceBuilder.build() , true);
+ }
+
+ public static void fillBfdParameters(List<BfdParams> bfdParams, IfTunnel ifTunnel) {
+ setBfdParamForEnable(bfdParams, ifTunnel != null ? ifTunnel.isMonitorEnabled() :true);
+ bfdParams.add(getBfdParams(BFD_PARAM_MIN_TX, ifTunnel != null ?
+ ifTunnel.getMonitorInterval().toString() : BFD_MIN_TX_VAL));
+ bfdParams.add(getBfdParams(BFD_PARAM_MIN_RX, BFD_MIN_RX_VAL));
+ bfdParams.add(getBfdParams(BFD_PARAM_DECAY_MIN_RX, BFD_DECAY_MIN_RX_VAL));
+ bfdParams.add(getBfdParams(BFD_PARAM_FORWARDING_IF_RX, BFD_FORWARDING_IF_RX_VAL));
+ bfdParams.add(getBfdParams(BFD_PARAM_CPATH_DOWN, BFD_CPATH_DOWN_VAL));
+ bfdParams.add(getBfdParams(BFD_PARAM_CHECK_TNL_KEY, BFD_CHECK_TNL_KEY_VAL));
+ }
+
+ public static void setBfdParamForEnable(List<BfdParams> bfdParams, boolean isEnabled) {
+ bfdParams.add(getBfdParams(BFD_PARAM_ENABLE, Boolean.toString(isEnabled)));
+ }
+
+ public static BfdParams getBfdParams(String key, String value) {
+ return new BfdParamsBuilder().setBfdParamKey(key).setKey(new BfdParamsKey(key))
+ .setBfdParamValue(value).build();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.utilities.SouthboundUtils;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+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.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class OvsInterfaceConfigAddHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceConfigAddHelper.class);
+
+ public static List<ListenableFuture<Void>> addConfiguration(DataBroker dataBroker, ParentRefs parentRefs,
+ Interface interfaceNew, IdManagerService idManager,
+ AlivenessMonitorService alivenessMonitorService,
+ IMdsalApiManager mdsalApiManager) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+
+ IfTunnel ifTunnel = interfaceNew.getAugmentation(IfTunnel.class);
+ if (ifTunnel != null) {
+ addTunnelConfiguration(dataBroker, parentRefs, interfaceNew, idManager, alivenessMonitorService,
+ mdsalApiManager, futures);
+ return futures;
+ }
+
+ addVlanConfiguration(interfaceNew, parentRefs, dataBroker, idManager, futures);
+ return futures;
+ }
+
+ private static void addVlanConfiguration(Interface interfaceNew, ParentRefs parentRefs, DataBroker dataBroker, IdManagerService idManager,
+ List<ListenableFuture<Void>> futures) {
+ IfL2vlan ifL2vlan = interfaceNew.getAugmentation(IfL2vlan.class);
+ if (ifL2vlan == null || (IfL2vlan.L2vlanMode.Trunk != ifL2vlan.getL2vlanMode() && IfL2vlan.L2vlanMode.Transparent != ifL2vlan.getL2vlanMode())) {
+ return;
+ }
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+ if(!InterfaceManagerCommonUtils.createInterfaceChildEntryIfNotPresent(dataBroker, transaction,
+ parentRefs.getParentInterface(), interfaceNew.getName())){
+ return;
+ }
+ LOG.debug("adding vlan configuration for {}",interfaceNew.getName());
+
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
+ InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(parentRefs.getParentInterface(), dataBroker);
+
+ if (ifState == null) {
+ LOG.debug("could not retrieve interface state corresponding to {}",interfaceNew.getName());
+ futures.add(transaction.submit());
+ return;
+ }
+
+ InterfaceManagerCommonUtils.addStateEntry(interfaceNew.getName(), transaction, dataBroker, idManager, ifState);
+
+ InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(interfaceNew.getName());
+ InterfaceParentEntry interfaceParentEntry =
+ InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceParentEntryKey, dataBroker);
+ if (interfaceParentEntry == null || interfaceParentEntry.getInterfaceChildEntry() == null) {
+ LOG.debug("could not retrieve interface parent info for {}",interfaceNew.getName());
+ futures.add(transaction.submit());
+ return;
+ }
+
+ //FIXME: If the no. of child entries exceeds 100, perform txn updates in batches of 100.
+ for (InterfaceChildEntry interfaceChildEntry : interfaceParentEntry.getInterfaceChildEntry()) {
+ InterfaceManagerCommonUtils.addStateEntry(interfaceChildEntry.getChildInterface(), transaction, dataBroker, idManager,ifState);
+ }
+ futures.add(transaction.submit());
+ }
+
+ private static void addTunnelConfiguration(DataBroker dataBroker, ParentRefs parentRefs,
+ Interface interfaceNew, IdManagerService idManager,
+ AlivenessMonitorService alivenessMonitorService,
+ IMdsalApiManager mdsalApiManager,
+ List<ListenableFuture<Void>> futures) {
+ LOG.debug("adding tunnel configuration for {}", interfaceNew.getName());
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+ if (parentRefs == null) {
+ LOG.warn("ParentRefs for interface: {} Not Found. " +
+ "Creation of Tunnel OF-Port not supported when dpid not provided.", interfaceNew.getName());
+ return;
+ }
+
+ BigInteger dpId = parentRefs.getDatapathNodeIdentifier();
+ if (dpId == null) {
+ LOG.warn("dpid for interface: {} Not Found. No DPID provided. " +
+ "Creation of OF-Port not supported.", interfaceNew.getName());
+ return;
+ }
+
+ BridgeEntryKey bridgeEntryKey = new BridgeEntryKey(dpId);
+ BridgeInterfaceEntryKey bridgeInterfaceEntryKey = new BridgeInterfaceEntryKey(interfaceNew.getName());
+
+ LOG.debug("creating bridge interfaceEntry in ConfigDS {}", bridgeEntryKey);
+ InterfaceMetaUtils.createBridgeInterfaceEntryInConfigDS(bridgeEntryKey, bridgeInterfaceEntryKey,
+ interfaceNew.getName(), transaction);
+ futures.add(transaction.submit());
+
+ // create bridge on switch, if switch is connected
+ BridgeRefEntryKey BridgeRefEntryKey = new BridgeRefEntryKey(dpId);
+ InstanceIdentifier<BridgeRefEntry> dpnBridgeEntryIid =
+ InterfaceMetaUtils.getBridgeRefEntryIdentifier(BridgeRefEntryKey);
+ BridgeRefEntry bridgeRefEntry =
+ InterfaceMetaUtils.getBridgeRefEntryFromOperDS(dpnBridgeEntryIid, dataBroker);
+ if(bridgeRefEntry != null && bridgeRefEntry.getBridgeReference() != null) {
+ LOG.debug("creating bridge interface on dpn {}", bridgeEntryKey);
+ InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid =
+ (InstanceIdentifier<OvsdbBridgeAugmentation>) bridgeRefEntry.getBridgeReference().getValue();
+ Optional<OvsdbBridgeAugmentation> bridgeNodeOptional =
+ IfmUtil.read(LogicalDatastoreType.OPERATIONAL, bridgeIid, dataBroker);
+ if (bridgeNodeOptional.isPresent()) {
+ OvsdbBridgeAugmentation ovsdbBridgeAugmentation = bridgeNodeOptional.get();
+ String bridgeName = ovsdbBridgeAugmentation.getBridgeName().getValue();
+ SouthboundUtils.addPortToBridge(bridgeIid, interfaceNew,
+ ovsdbBridgeAugmentation, bridgeName, interfaceNew.getName(), dataBroker, futures);
+
+ // if TEP is already configured on switch, start LLDP monitoring and program tunnel ingress flow
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
+ InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceNew.getName(), dataBroker);
+ if(ifState != null){
+ NodeConnectorId ncId = IfmUtil.getNodeConnectorIdFromInterface(ifState);
+ if(ncId != null) {
+ long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(ncId));
+ InterfaceManagerCommonUtils.makeTunnelIngressFlow(futures, mdsalApiManager, interfaceNew.getAugmentation(IfTunnel.class),
+ dpId, portNo, interfaceNew, ifState.getIfIndex(), NwConstants.ADD_FLOW);
+ // start LLDP monitoring for the tunnel interface
+ AlivenessMonitorUtils.startLLDPMonitoring(alivenessMonitorService, dataBroker, interfaceNew);
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.idmanager.IdManager;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.utilities.SouthboundUtils;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+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.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorStopInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.MonitorStopInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+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 OvsInterfaceConfigRemoveHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceConfigRemoveHelper.class);
+
+ public static List<ListenableFuture<Void>> removeConfiguration(DataBroker dataBroker, AlivenessMonitorService alivenessMonitorService,
+ Interface interfaceOld,
+ IdManagerService idManager,
+ IMdsalApiManager mdsalApiManager,
+ ParentRefs parentRefs) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+
+ IfTunnel ifTunnel = interfaceOld.getAugmentation(IfTunnel.class);
+ if (ifTunnel != null) {
+ removeTunnelConfiguration(alivenessMonitorService, parentRefs, dataBroker, interfaceOld,
+ idManager, mdsalApiManager, futures);
+ }else {
+ removeVlanConfiguration(dataBroker, parentRefs, interfaceOld, t);
+ futures.add(t.submit());
+ }
+ return futures;
+ }
+
+ private static void removeVlanConfiguration(DataBroker dataBroker, ParentRefs parentRefs, Interface interfaceOld, WriteTransaction transaction) {
+ LOG.debug("removing vlan configuration for {}",interfaceOld.getName());
+ IfL2vlan ifL2vlan = interfaceOld.getAugmentation(IfL2vlan.class);
+ if (ifL2vlan == null || (IfL2vlan.L2vlanMode.Trunk != ifL2vlan.getL2vlanMode() && IfL2vlan.L2vlanMode.Transparent != ifL2vlan.getL2vlanMode())) {
+ return;
+ }
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
+ InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceOld.getName(), dataBroker);
+ if (ifState == null) {
+ LOG.debug("could not fetch interface state corresponding to {}",interfaceOld.getName());
+ return;
+ }
+
+ InterfaceManagerCommonUtils.deleteStateEntry(interfaceOld.getName(), transaction);
+
+ BigInteger dpId = IfmUtil.getDpnFromInterface(ifState);
+ FlowBasedServicesUtils.removeIngressFlow(interfaceOld.getName(), dpId, transaction);
+ InterfaceManagerCommonUtils.deleteParentInterfaceEntry(transaction, parentRefs.getParentInterface());
+ // For Vlan-Trunk Interface, remove the trunk-member operstates as well...
+
+ InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(interfaceOld.getName());
+ InterfaceParentEntry interfaceParentEntry =
+ InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceParentEntryKey, dataBroker);
+ if (interfaceParentEntry == null || interfaceParentEntry.getInterfaceChildEntry() == null) {
+ return;
+ }
+
+ //FIXME: If the no. of child entries exceeds 100, perform txn updates in batches of 100.
+ for (InterfaceChildEntry interfaceChildEntry : interfaceParentEntry.getInterfaceChildEntry()) {
+ LOG.debug("removing interface state for vlan trunk member {}",interfaceChildEntry.getChildInterface());
+ InterfaceManagerCommonUtils.deleteStateEntry(interfaceChildEntry.getChildInterface(), transaction);
+ FlowBasedServicesUtils.removeIngressFlow(interfaceChildEntry.getChildInterface(), dpId, transaction);
+ }
+ }
+
+ private static void removeTunnelConfiguration(AlivenessMonitorService alivenessMonitorService, ParentRefs parentRefs,
+ DataBroker dataBroker, Interface interfaceOld,
+ IdManagerService idManager, IMdsalApiManager mdsalApiManager,
+ List<ListenableFuture<Void>> futures) {
+ LOG.debug("removing tunnel configuration for {}",interfaceOld.getName());
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ BigInteger dpId = null;
+ if (parentRefs != null) {
+ dpId = parentRefs.getDatapathNodeIdentifier();
+ }
+
+ if (dpId == null) {
+ return;
+ }
+
+ BridgeRefEntryKey bridgeRefEntryKey = new BridgeRefEntryKey(dpId);
+ InstanceIdentifier<BridgeRefEntry> bridgeRefEntryIid =
+ InterfaceMetaUtils.getBridgeRefEntryIdentifier(bridgeRefEntryKey);
+ BridgeRefEntry bridgeRefEntry =
+ InterfaceMetaUtils.getBridgeRefEntryFromOperDS(bridgeRefEntryIid, dataBroker);
+
+ if (bridgeRefEntry != null) {
+ LOG.debug("removing termination point for {}",interfaceOld.getName());
+ InstanceIdentifier<?> bridgeIid = bridgeRefEntry.getBridgeReference().getValue();
+ InstanceIdentifier<TerminationPoint> tpIid = SouthboundUtils.createTerminationPointInstanceIdentifier(
+ InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), interfaceOld.getName());
+ t.delete(LogicalDatastoreType.CONFIGURATION, tpIid);
+
+ // delete tunnel ingress flow
+ LOG.debug("removing tunnel ingress flow for {}",interfaceOld.getName());
+ NodeConnectorId ncId = IfmUtil.getNodeConnectorIdFromInterface(interfaceOld, dataBroker);
+ long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(ncId));
+ InterfaceManagerCommonUtils.makeTunnelIngressFlow(futures, mdsalApiManager,
+ interfaceOld.getAugmentation(IfTunnel.class),
+ dpId, portNo, interfaceOld, -1,
+ NwConstants.DEL_FLOW);
+ }
+
+ BridgeEntryKey bridgeEntryKey = new BridgeEntryKey(dpId);
+ InstanceIdentifier<BridgeEntry> bridgeEntryIid = InterfaceMetaUtils.getBridgeEntryIdentifier(bridgeEntryKey);
+ BridgeEntry bridgeEntry = InterfaceMetaUtils.getBridgeEntryFromConfigDS(bridgeEntryIid, dataBroker);
+ if (bridgeEntry == null) {
+ return;
+ }
+
+ List<BridgeInterfaceEntry> bridgeInterfaceEntries = bridgeEntry.getBridgeInterfaceEntry();
+ if (bridgeInterfaceEntries == null) {
+ return;
+ }
+
+ if (bridgeInterfaceEntries.size() <= 1) {
+ t.delete(LogicalDatastoreType.CONFIGURATION, bridgeEntryIid);
+ } else {
+ BridgeInterfaceEntryKey bridgeInterfaceEntryKey =
+ new BridgeInterfaceEntryKey(interfaceOld.getName());
+ InstanceIdentifier<BridgeInterfaceEntry> bridgeInterfaceEntryIid =
+ InterfaceMetaUtils.getBridgeInterfaceEntryIdentifier(bridgeEntryKey,
+ bridgeInterfaceEntryKey);
+ t.delete(LogicalDatastoreType.CONFIGURATION, bridgeInterfaceEntryIid);
+ }
+ futures.add(t.submit());
+ // stop LLDP monitoring for the tunnel interface
+ AlivenessMonitorUtils.stopLLDPMonitoring(alivenessMonitorService, dataBroker, interfaceOld);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.utilities.SouthboundUtils;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+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.state.Interface.OperStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class OvsInterfaceConfigUpdateHelper{
+ private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceConfigUpdateHelper.class);
+
+ public static List<ListenableFuture<Void>> updateConfiguration(DataBroker dataBroker, AlivenessMonitorService alivenessMonitorService,
+ IdManagerService idManager, IMdsalApiManager mdsalApiManager,
+ Interface interfaceNew, Interface interfaceOld) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+
+ // If any of the port attributes are modified, treat it as a delete and recreate scenario
+ if(portAttributesModified(interfaceOld, interfaceNew)) {
+ futures.addAll(OvsInterfaceConfigRemoveHelper.removeConfiguration(dataBroker, alivenessMonitorService, interfaceOld, idManager,
+ mdsalApiManager, interfaceOld.getAugmentation(ParentRefs.class)));
+ futures.addAll(OvsInterfaceConfigAddHelper.addConfiguration(dataBroker,
+ interfaceNew.getAugmentation(ParentRefs.class), interfaceNew, idManager,alivenessMonitorService,mdsalApiManager));
+ return futures;
+ }
+
+ // If there is no operational state entry for the interface, treat it as create
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
+ InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceNew.getName(), dataBroker);
+ if (ifState == null) {
+ futures.addAll(OvsInterfaceConfigAddHelper.addConfiguration(dataBroker,
+ interfaceNew.getAugmentation(ParentRefs.class), interfaceNew, idManager, alivenessMonitorService, mdsalApiManager));
+ return futures;
+ }
+
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+ if(TunnelMonitoringAttributesModified(interfaceOld, interfaceNew)){
+ handleTunnelMonitorUpdates(futures, transaction, alivenessMonitorService, interfaceNew,
+ interfaceOld, dataBroker);
+ return futures;
+ }
+
+ if (interfaceNew.isEnabled() != interfaceOld.isEnabled()) {
+ handleInterfaceAdminStateUpdates(futures, transaction, interfaceNew, dataBroker, ifState);
+ }
+
+ futures.add(transaction.submit());
+ return futures;
+ }
+
+ private static boolean portAttributesModified(Interface interfaceOld, Interface interfaceNew) {
+ ParentRefs parentRefsOld = interfaceOld.getAugmentation(ParentRefs.class);
+ ParentRefs parentRefsNew = interfaceNew.getAugmentation(ParentRefs.class);
+ if (checkAugmentations(parentRefsOld, parentRefsNew)) {
+ return true;
+ }
+
+ IfL2vlan ifL2vlanOld = interfaceOld.getAugmentation(IfL2vlan.class);
+ IfL2vlan ifL2vlanNew = interfaceNew.getAugmentation(IfL2vlan.class);
+ if (checkAugmentations(ifL2vlanOld, ifL2vlanNew)) {
+ return true;
+ }
+
+ IfTunnel ifTunnelOld = interfaceOld.getAugmentation(IfTunnel.class);
+ IfTunnel ifTunnelNew = interfaceNew.getAugmentation(IfTunnel.class);
+ if (checkAugmentations(ifTunnelOld, ifTunnelNew)) {
+ if(!ifTunnelNew.getTunnelDestination().equals(ifTunnelOld.getTunnelDestination()) ||
+ !ifTunnelNew.getTunnelSource().equals(ifTunnelOld.getTunnelSource()) ||
+ !ifTunnelNew.getTunnelGateway().equals(ifTunnelOld.getTunnelGateway())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private static boolean TunnelMonitoringAttributesModified(Interface interfaceOld, Interface interfaceNew) {
+ IfTunnel ifTunnelOld = interfaceOld.getAugmentation(IfTunnel.class);
+ IfTunnel ifTunnelNew = interfaceNew.getAugmentation(IfTunnel.class);
+ if (checkAugmentations(ifTunnelOld, ifTunnelNew)) {
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * if the tunnel monitoring attributes have changed, handle it based on the tunnel type.
+ * As of now internal vxlan tunnels use LLDP monitoring and external tunnels use BFD monitoring.
+ */
+ private static void handleTunnelMonitorUpdates(List<ListenableFuture<Void>> futures, WriteTransaction transaction,
+ AlivenessMonitorService alivenessMonitorService,
+ Interface interfaceNew, Interface interfaceOld, DataBroker dataBroker){
+ LOG.debug("tunnel monitoring attributes modified for interface {}", interfaceNew.getName());
+ // update termination point on switch, if switch is connected
+ BridgeRefEntry bridgeRefEntry =
+ InterfaceMetaUtils.getBridgeReferenceForInterface(interfaceNew, dataBroker);
+ if(InterfaceMetaUtils.bridgeExists(bridgeRefEntry, dataBroker)) {
+ SouthboundUtils.updateBfdParamtersForTerminationPoint(bridgeRefEntry.getBridgeReference().getValue(),
+ interfaceNew.getAugmentation(IfTunnel.class),
+ interfaceNew.getName(), transaction);
+ }
+
+ // stop tunnel monitoring if admin state is disabled for an internal vxlan trunk interface
+ if(interfaceOld.isEnabled() && !interfaceNew.isEnabled()) {
+ AlivenessMonitorUtils.stopLLDPMonitoring(alivenessMonitorService, dataBroker, interfaceNew);
+ }else{
+ AlivenessMonitorUtils.handleTunnelMonitorUpdates(alivenessMonitorService, dataBroker, interfaceOld, interfaceNew);
+ }
+ futures.add(transaction.submit());
+ }
+
+ private static void handleInterfaceAdminStateUpdates(List<ListenableFuture<Void>> futures, WriteTransaction transaction,
+ Interface interfaceNew, DataBroker dataBroker,
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState){
+ OperStatus operStatus = InterfaceManagerCommonUtils.updateStateEntry(interfaceNew, dataBroker, transaction, ifState);
+
+ IfL2vlan ifL2vlan = interfaceNew.getAugmentation(IfL2vlan.class);
+ if (ifL2vlan == null || (IfL2vlan.L2vlanMode.Trunk != ifL2vlan.getL2vlanMode() && IfL2vlan.L2vlanMode.Transparent != ifL2vlan.getL2vlanMode())) {
+ futures.add(transaction.submit());
+ return;
+ }
+
+ InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(interfaceNew.getName());
+ InterfaceParentEntry interfaceParentEntry =
+ InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceParentEntryKey, dataBroker);
+ if (interfaceParentEntry == null || interfaceParentEntry.getInterfaceChildEntry() == null) {
+ futures.add(transaction.submit());
+ return;
+ }
+
+ for (InterfaceChildEntry interfaceChildEntry : interfaceParentEntry.getInterfaceChildEntry()) {
+ InterfaceManagerCommonUtils.updateOperStatus(interfaceChildEntry.getChildInterface(), operStatus, transaction);
+ }
+ }
+
+ private static<T> boolean checkAugmentations(T oldAug, T newAug) {
+ if ((oldAug != null && newAug == null) ||
+ (oldAug == null && newAug != null)) {
+ return true;
+ }
+
+ if (newAug != null && oldAug != null && !newAug.equals(oldAug)) {
+ return true;
+ }
+
+ return false;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+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.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class OvsVlanMemberConfigAddHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(OvsVlanMemberConfigAddHelper.class);
+ public static List<ListenableFuture<Void>> addConfiguration(DataBroker dataBroker, ParentRefs parentRefs,
+ Interface interfaceNew, IfL2vlan ifL2vlan,
+ IdManagerService idManager) {
+ LOG.debug("add vlan member configuration {}",interfaceNew.getName());
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+
+ InterfaceManagerCommonUtils.createInterfaceChildEntry(t, parentRefs.getParentInterface(), interfaceNew.getName());
+
+ InterfaceKey interfaceKey = new InterfaceKey(parentRefs.getParentInterface());
+ Interface ifaceParent = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+ if (ifaceParent == null) {
+ LOG.info("Parent Interface: {} not found when adding child interface: {}",
+ parentRefs.getParentInterface(), interfaceNew.getName());
+ futures.add(t.submit());
+ return futures;
+ }
+
+ IfL2vlan parentIfL2Vlan = ifaceParent.getAugmentation(IfL2vlan.class);
+ if (parentIfL2Vlan == null || parentIfL2Vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Trunk) {
+ LOG.error("Parent Interface: {} not of trunk Type when adding trunk-member: {}", ifaceParent, interfaceNew);
+ futures.add(t.submit());
+ return futures;
+ }
+
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
+ InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(parentRefs.getParentInterface(), dataBroker);
+ if (ifState != null) {
+ LOG.debug("add interface state info for vlan member {}",interfaceNew.getName());
+ InterfaceManagerCommonUtils.addStateEntry(interfaceNew.getName(), t, dataBroker, idManager, ifState);
+ }
+
+ futures.add(t.submit());
+ return futures;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.renderer.ovs.confighelpers;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
+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.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class OvsVlanMemberConfigRemoveHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(OvsVlanMemberConfigRemoveHelper.class);
+ public static List<ListenableFuture<Void>> removeConfiguration(DataBroker dataBroker, ParentRefs parentRefs,
+ Interface interfaceOld, IfL2vlan ifL2vlan,
+ IdManagerService idManager) {
+ LOG.debug("remove vlan member configuration {}",interfaceOld.getName());
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+
+ InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(parentRefs.getParentInterface());
+ InstanceIdentifier<InterfaceParentEntry> interfaceParentEntryIid =
+ InterfaceMetaUtils.getInterfaceParentEntryIdentifier(interfaceParentEntryKey);
+ InterfaceParentEntry interfaceParentEntry =
+ InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceParentEntryIid, dataBroker);
+
+ if(interfaceParentEntry == null){
+ return futures;
+ }
+
+ //Delete the interface child information
+ List<InterfaceChildEntry> interfaceChildEntries = interfaceParentEntry.getInterfaceChildEntry();
+ InterfaceChildEntryKey interfaceChildEntryKey = new InterfaceChildEntryKey(interfaceOld.getName());
+ InstanceIdentifier<InterfaceChildEntry> interfaceChildEntryIid =
+ InterfaceMetaUtils.getInterfaceChildEntryIdentifier(interfaceParentEntryKey, interfaceChildEntryKey);
+ t.delete(LogicalDatastoreType.CONFIGURATION, interfaceChildEntryIid);
+ //If this is the last child, remove the interface parent info as well.
+ if (interfaceChildEntries.size() <= 1) {
+ t.delete(LogicalDatastoreType.CONFIGURATION, interfaceParentEntryIid);
+ }
+
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
+ InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(parentRefs.getParentInterface(), dataBroker);
+ if (ifState != null) {
+ /* FIXME -- The below code is needed if vlan-trunks should be updated in the of-port
+
+ String lowerLayerIf = ifState.getLowerLayerIf().get(0);
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+
+ BridgeRefEntryKey BridgeRefEntryKey = new BridgeRefEntryKey(dpId);
+ InstanceIdentifier<BridgeRefEntry> dpnBridgeEntryIid =
+ InterfaceMetaUtils.getBridgeRefEntryIdentifier(BridgeRefEntryKey);
+ BridgeRefEntry bridgeRefEntry =
+ InterfaceMetaUtils.getBridgeRefEntryFromOperDS(dpnBridgeEntryIid, dataBroker);
+ if (bridgeRefEntry != null) {
+ InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid =
+ (InstanceIdentifier<OvsdbBridgeAugmentation>)bridgeRefEntry.getBridgeReference().getValue();
+ Optional<OvsdbBridgeAugmentation> bridgeNodeOptional =
+ IfmUtil.read(LogicalDatastoreType.OPERATIONAL, bridgeIid, dataBroker);
+ if (bridgeNodeOptional.isPresent()) {
+ OvsdbBridgeAugmentation ovsdbBridgeAugmentation = bridgeNodeOptional.get();
+ String bridgeName = ovsdbBridgeAugmentation.getBridgeName().getValue();
+ VlanTrunkSouthboundUtils.updateVlanMemberInTrunk(bridgeIid, ifL2vlan,
+ ovsdbBridgeAugmentation, bridgeName, parentRefs.getParentInterface(), dataBroker, t);
+ }
+ } */
+
+ LOG.debug("delete vlan member interface state {}",interfaceOld.getName());
+ BigInteger dpId = IfmUtil.getDpnFromInterface(ifState);
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
+ IfmUtil.buildStateInterfaceId(interfaceOld.getName());
+ t.delete(LogicalDatastoreType.OPERATIONAL, ifStateId);
+ FlowBasedServicesUtils.removeIngressFlow(interfaceOld.getName(), dpId, t);
+ }
+
+ futures.add(t.submit());
+ return futures;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.renderer.ovs.confighelpers;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.idmanager.IdManager;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+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.state.Interface.OperStatus;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class OvsVlanMemberConfigUpdateHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(OvsVlanMemberConfigUpdateHelper.class);
+ public static List<ListenableFuture<Void>> updateConfiguration(DataBroker dataBroker, AlivenessMonitorService alivenessMonitorService, ParentRefs parentRefsNew,
+ Interface interfaceOld, IfL2vlan ifL2vlanNew,
+ Interface interfaceNew, IdManagerService idManager,
+ IMdsalApiManager mdsalApiManager) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ ParentRefs parentRefsOld = interfaceOld.getAugmentation(ParentRefs.class);
+
+ InterfaceParentEntryKey interfaceParentEntryKey =
+ new InterfaceParentEntryKey(parentRefsOld.getParentInterface());
+ InterfaceChildEntryKey interfaceChildEntryKey = new InterfaceChildEntryKey(interfaceOld.getName());
+ InterfaceChildEntry interfaceChildEntry =
+ InterfaceMetaUtils.getInterfaceChildEntryFromConfigDS(interfaceParentEntryKey, interfaceChildEntryKey,
+ dataBroker);
+
+ if (interfaceChildEntry == null) {
+ futures.addAll(OvsInterfaceConfigAddHelper.addConfiguration(dataBroker,
+ interfaceNew.getAugmentation(ParentRefs.class), interfaceNew, idManager, alivenessMonitorService, mdsalApiManager));
+ return futures;
+ }
+
+ IfL2vlan ifL2vlanOld = interfaceOld.getAugmentation(IfL2vlan.class);
+ if (ifL2vlanOld == null || (ifL2vlanNew.getL2vlanMode() != ifL2vlanOld.getL2vlanMode())) {
+ LOG.error("Configuration Error. Vlan Mode Change of Vlan Trunk Member {} as new trunk member: {} is " +
+ "not allowed.", interfaceOld, interfaceNew);
+ return futures;
+ }
+
+ if (ifL2vlanOld.getVlanId() != ifL2vlanNew.getVlanId() ||
+ !parentRefsOld.getParentInterface().equals(parentRefsNew.getParentInterface())) {
+ futures.addAll(OvsVlanMemberConfigRemoveHelper.removeConfiguration(dataBroker, parentRefsOld, interfaceOld,
+ ifL2vlanOld, idManager));
+ futures.addAll(OvsVlanMemberConfigAddHelper.addConfiguration(dataBroker, parentRefsNew, interfaceNew,
+ ifL2vlanNew, idManager));
+ return futures;
+ }
+
+ if (interfaceNew.isEnabled() == interfaceOld.isEnabled()) {
+ return futures;
+ }
+
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface pifState =
+ InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(parentRefsNew.getParentInterface(), dataBroker);
+ if (pifState != null) {
+ OperStatus operStatus = OperStatus.Down;
+ if (interfaceNew.isEnabled()) {
+ operStatus = pifState.getOperStatus();
+ }
+
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
+ IfmUtil.buildStateInterfaceId(interfaceNew.getName());
+ InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
+ ifaceBuilder.setOperStatus(operStatus);
+ ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(interfaceNew.getName()));
+
+ t.merge(LogicalDatastoreType.OPERATIONAL, ifStateId, ifaceBuilder.build());
+ futures.add(t.submit());
+ }
+
+ return futures;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.renderer.ovs.statehelpers;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+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;
+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.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * This worker is responsible for adding the openflow-interfaces/of-port-info container
+ * in odl-interface-openflow yang.
+ * Where applicable:
+ * Create the entries in Interface-State OperDS.
+ * Create the entries in Inventory OperDS.
+ */
+
+public class OvsInterfaceStateAddHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceStateAddHelper.class);
+
+ public static List<ListenableFuture<Void>> addState(DataBroker dataBroker, IdManagerService idManager,
+ IMdsalApiManager mdsalApiManager,AlivenessMonitorService alivenessMonitorService,
+ NodeConnectorId nodeConnectorId, String portName, FlowCapableNodeConnector fcNodeConnectorNew) {
+ LOG.debug("Adding Interface State to Oper DS for port: {}", portName);
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+
+ //Retrieve PbyAddress & OperState from the DataObject
+ PhysAddress physAddress = new PhysAddress(fcNodeConnectorNew.getHardwareAddress().getValue());
+ /*FIXME
+ State state = fcNodeConnectorNew.getState();
+ Interface.OperStatus operStatus =
+ fcNodeConnectorNew == null ? Interface.OperStatus.Down : Interface.OperStatus.Up;
+ Interface.AdminStatus adminStatus = state.isBlocked() ? Interface.AdminStatus.Down : Interface.AdminStatus.Up;
+ */
+ Interface.OperStatus operStatus = Interface.OperStatus.Up;
+ Interface.AdminStatus adminStatus = Interface.AdminStatus.Up;
+
+ // Fetch the interface name corresponding to the port Name
+ InterfaceKey interfaceKey = new InterfaceKey(portName);
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
+ InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+
+ Interface ifState = InterfaceManagerCommonUtils.addStateEntry(iface, portName, transaction, idManager,
+ physAddress, operStatus, adminStatus, nodeConnectorId);
+ // If this interface is a tunnel interface, create the tunnel ingress flow
+ if(iface != null) {
+ IfTunnel tunnel = iface.getAugmentation(IfTunnel.class);
+ if (tunnel != null) {
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
+ InterfaceManagerCommonUtils.makeTunnelIngressFlow(futures, mdsalApiManager, tunnel, dpId, portNo, iface,
+ ifState.getIfIndex(), NwConstants.ADD_FLOW);
+ futures.add(transaction.submit());
+ AlivenessMonitorUtils.startLLDPMonitoring(alivenessMonitorService, dataBroker, iface);
+ return futures;
+ }
+ }
+
+ // For all other interfaces except tunnel interfaces, interface name won't be same as port name.
+ // In that case fetch the interface corresponding to the portName, and update the state accordingly
+ InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(portName);
+ InterfaceParentEntry interfaceParentEntry =
+ InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceParentEntryKey, dataBroker);
+ if (interfaceParentEntry == null || interfaceParentEntry.getInterfaceChildEntry() == null) {
+ futures.add(transaction.submit());
+ return futures;
+ }
+
+ //FIXME: If the no. of child entries exceeds 100, perform txn updates in batches of 100.
+ //List<Trunks> trunks = new ArrayList<>();
+
+ String higherlayerChild = interfaceParentEntry.getInterfaceChildEntry().get(0).getChildInterface();
+ InterfaceManagerCommonUtils.addStateEntry(higherlayerChild, transaction, dataBroker, idManager,
+ ifState);
+
+ // If this interface maps to a Vlan trunk entity, operational states of all the vlan-trunk-members
+ // should also be created here.
+ InterfaceParentEntryKey higherLayerParentEntryKey = new InterfaceParentEntryKey(higherlayerChild);
+ InterfaceParentEntry higherLayerParent =
+ InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(higherLayerParentEntryKey, dataBroker);
+ if(higherLayerParent != null && higherLayerParent.getInterfaceChildEntry() != null) {
+ for (InterfaceChildEntry interfaceChildEntry : higherLayerParent.getInterfaceChildEntry()){
+ InterfaceManagerCommonUtils.addStateEntry(interfaceChildEntry.getChildInterface(), transaction, dataBroker, idManager,
+ ifState);
+ }
+ }
+ /** Below code will be needed if we want to update the vlan-trunks on the of-port
+ if (trunks.isEmpty()) {
+ futures.add(t.submit());
+ return futures;
+ }
+
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+
+ BridgeRefEntryKey BridgeRefEntryKey = new BridgeRefEntryKey(dpId);
+ InstanceIdentifier<BridgeRefEntry> dpnBridgeEntryIid =
+ InterfaceMetaUtils.getBridgeRefEntryIdentifier(BridgeRefEntryKey);
+ BridgeRefEntry bridgeRefEntry =
+ InterfaceMetaUtils.getBridgeRefEntryFromOperDS(dpnBridgeEntryIid, dataBroker);
+ if (bridgeRefEntry == null) {
+ futures.add(t.submit());
+ return futures;
+ }
+
+ InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid =
+ (InstanceIdentifier<OvsdbBridgeAugmentation>)bridgeRefEntry.getBridgeReference().getValue();
+ VlanTrunkSouthboundUtils.addTerminationPointWithTrunks(bridgeIid, trunks, iface.getName(), t);
+ */
+
+ futures.add(transaction.submit());
+ return futures;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.interfacemgr.renderer.ovs.statehelpers;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+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;
+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.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+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.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+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 OvsInterfaceStateRemoveHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceStateRemoveHelper.class);
+
+ public static List<ListenableFuture<Void>> removeState(IdManagerService idManager, IMdsalApiManager mdsalApiManager,
+ AlivenessMonitorService alivenessMonitorService,
+ InstanceIdentifier<FlowCapableNodeConnector> key,
+ DataBroker dataBroker, String portName, FlowCapableNodeConnector fcNodeConnectorOld) {
+ LOG.debug("Removing interface-state for port: {}", portName);
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+
+ InstanceIdentifier<Interface> ifStateId = IfmUtil.buildStateInterfaceId(portName);
+
+ // delete the port entry from interface operational DS
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
+ InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(portName, dataBroker);
+ transaction.delete(LogicalDatastoreType.OPERATIONAL, ifStateId);
+
+ InterfaceKey interfaceKey = new InterfaceKey(portName);
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
+ InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+
+ NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ // If this interface is a tunnel interface, remove the tunnel ingress flow and stop lldp monitoring
+ if(iface != null) {
+ IfTunnel tunnel = iface.getAugmentation(IfTunnel.class);
+ if (tunnel != null) {
+ long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
+ InterfaceManagerCommonUtils.makeTunnelIngressFlow(futures, mdsalApiManager, tunnel, dpId, portNo, iface, -1,
+ NwConstants.DEL_FLOW);
+ futures.add(transaction.submit());
+ AlivenessMonitorUtils.stopLLDPMonitoring(alivenessMonitorService, dataBroker, iface);
+ return futures;
+ }
+ }
+
+ InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(portName);
+ InterfaceParentEntry interfaceParentEntry =
+ InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceParentEntryKey, dataBroker);
+ if (interfaceParentEntry == null || interfaceParentEntry.getInterfaceChildEntry() == null) {
+ futures.add(transaction.submit());
+ return futures;
+ }
+
+ //FIXME: If the no. of child entries exceeds 100, perform txn updates in batches of 100.
+ InterfaceChildEntry higherlayerChild = interfaceParentEntry.getInterfaceChildEntry().get(0);
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface>
+ higerLayerChildIfStateId = IfmUtil.buildStateInterfaceId(higherlayerChild.getChildInterface());
+ Interface higherLayerIfChildState = InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(higherlayerChild.getChildInterface(), dataBroker);
+ if (interfaceState != null && higherLayerIfChildState != null) {
+ transaction.delete(LogicalDatastoreType.OPERATIONAL, higerLayerChildIfStateId);
+ FlowBasedServicesUtils.removeIngressFlow(higherLayerIfChildState.getName(), dpId, transaction);
+ }
+ // If this interface maps to a Vlan trunk entity, operational states of all the vlan-trunk-members
+ // should also be created here.
+ InterfaceParentEntryKey higherLayerParentEntryKey = new InterfaceParentEntryKey(higherlayerChild.getChildInterface());
+ InterfaceParentEntry higherLayerParent =
+ InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(higherLayerParentEntryKey, dataBroker);
+
+ if(higherLayerParent != null && higherLayerParent.getInterfaceChildEntry() != null) {
+ for (InterfaceChildEntry interfaceChildEntry : higherLayerParent.getInterfaceChildEntry()) {
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifChildStateId =
+ IfmUtil.buildStateInterfaceId(interfaceChildEntry.getChildInterface());
+ Interface childInterfaceState = InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceChildEntry.getChildInterface(), dataBroker);
+ if (childInterfaceState != null) {
+ transaction.delete(LogicalDatastoreType.OPERATIONAL, ifChildStateId);
+ FlowBasedServicesUtils.removeIngressFlow(childInterfaceState.getName(), dpId, transaction);
+ }
+ }
+ }
+
+
+ /* Below code will be needed if we want to update the vlan-trunk in the of-port.
+ NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+
+ BridgeRefEntryKey BridgeRefEntryKey = new BridgeRefEntryKey(dpId);
+ InstanceIdentifier<BridgeRefEntry> dpnBridgeEntryIid =
+ InterfaceMetaUtils.getBridgeRefEntryIdentifier(BridgeRefEntryKey);
+ BridgeRefEntry bridgeRefEntry =
+ InterfaceMetaUtils.getBridgeRefEntryFromOperDS(dpnBridgeEntryIid, dataBroker);
+ if (bridgeRefEntry == null) {
+ futures.add(t.submit());
+ return futures;
+ }
+
+ InstanceIdentifier<?> bridgeIid = bridgeRefEntry.getBridgeReference().getValue();
+ InstanceIdentifier<TerminationPoint> tpIid = SouthboundUtils.createTerminationPointInstanceIdentifier(
+ InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), interfaceOld.getName());
+ t.delete(LogicalDatastoreType.CONFIGURATION, tpIid); */
+
+ futures.add(transaction.submit());
+ return futures;
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.interfacemgr.renderer.ovs.statehelpers;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+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.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+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 OvsInterfaceStateUpdateHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceStateUpdateHelper.class);
+
+ public static List<ListenableFuture<Void>> updateState(InstanceIdentifier<FlowCapableNodeConnector> key,
+ AlivenessMonitorService alivenessMonitorService,
+ DataBroker dataBroker, String portName,
+ FlowCapableNodeConnector flowCapableNodeConnectorNew,
+ FlowCapableNodeConnector flowCapableNodeConnectorOld) {
+ LOG.debug("Update of Interface State for port: {}", portName);
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+
+ Interface.OperStatus operStatusNew = getOpState(flowCapableNodeConnectorNew);
+ MacAddress macAddressNew = flowCapableNodeConnectorNew.getHardwareAddress();
+
+ Interface.OperStatus operStatusOld = getOpState(flowCapableNodeConnectorOld);
+ MacAddress macAddressOld = flowCapableNodeConnectorOld.getHardwareAddress();
+
+ boolean opstateModified = false;
+ boolean hardwareAddressModified = false;
+ if (!operStatusNew.equals(operStatusOld)) {
+ opstateModified = true;
+ }
+ if (!macAddressNew.equals(macAddressOld)) {
+ hardwareAddressModified = true;
+ }
+
+ if (!opstateModified && !hardwareAddressModified) {
+ LOG.debug("If State entry for port: {} Not Modified.", portName);
+ return futures;
+ }
+
+ InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
+ if (hardwareAddressModified) {
+ LOG.debug("Hw-Address Modified for Port: {}", portName);
+ PhysAddress physAddress = new PhysAddress(macAddressNew.getValue());
+ ifaceBuilder.setPhysAddress(physAddress);
+ }
+
+ NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
+ handleInterfaceStateUpdates(portName, nodeConnectorId,
+ transaction, dataBroker, ifaceBuilder, opstateModified, operStatusNew);
+
+ InterfaceParentEntry interfaceParentEntry =
+ InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(portName, dataBroker);
+ if (interfaceParentEntry != null && interfaceParentEntry.getInterfaceChildEntry() != null) {
+ for (InterfaceChildEntry higherlayerChild : interfaceParentEntry.getInterfaceChildEntry()) {
+ handleInterfaceStateUpdates(higherlayerChild.getChildInterface(),
+ nodeConnectorId, transaction, dataBroker, ifaceBuilder, opstateModified, operStatusNew);
+ InterfaceParentEntry higherLayerParent =
+ InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(higherlayerChild.getChildInterface(), dataBroker);
+ if (higherLayerParent != null && higherLayerParent.getInterfaceChildEntry() != null) {
+ for (InterfaceChildEntry interfaceChildEntry : higherLayerParent.getInterfaceChildEntry()) {
+ //FIXME: If the no. of child entries exceeds 100, perform txn updates in batches of 100.
+ handleInterfaceStateUpdates(interfaceChildEntry.getChildInterface(), nodeConnectorId,
+ transaction, dataBroker, ifaceBuilder, opstateModified, operStatusNew);
+ }
+ }
+ }
+ }else {
+ handleTunnelMonitoringUpdates(alivenessMonitorService, dataBroker, iface, operStatusNew, opstateModified);
+ }
+ futures.add(transaction.submit());
+ return futures;
+ }
+
+ public static Interface.OperStatus getOpState(FlowCapableNodeConnector flowCapableNodeConnector){
+ Interface.OperStatus operStatus =
+ (flowCapableNodeConnector.getState().isLive() &&
+ !flowCapableNodeConnector.getConfiguration().isPORTDOWN())
+ ? Interface.OperStatus.Up: Interface.OperStatus.Down;
+ return operStatus;
+ }
+
+ public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
+ handleInterfaceStateUpdates(String interfaceName, NodeConnectorId nodeConnectorId,WriteTransaction transaction,
+ DataBroker dataBroker, InterfaceBuilder ifaceBuilder, boolean opStateModified,
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus opState){
+ LOG.debug("updating interface state entry for {}", interfaceName);
+ InstanceIdentifier<Interface> ifStateId = IfmUtil.buildStateInterfaceId(interfaceName);
+ ifaceBuilder.setKey(new InterfaceKey(interfaceName));
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
+ InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceName, dataBroker);
+ if (modifyOpState(iface, opStateModified)) {
+ LOG.debug("updating interface oper status as {} for {}", opState.name(), interfaceName);
+ ifaceBuilder.setOperStatus(opState);
+ }
+ transaction.merge(LogicalDatastoreType.OPERATIONAL, ifStateId, ifaceBuilder.build());
+
+ // if opstate has changed, add or remove ingress flow for l2vlan interfaces accordingly
+ if(modifyIngressFlow(iface, opStateModified)) {
+ handleVlanIngressFlowUpdates(dataBroker, opState, transaction, iface, nodeConnectorId, ifStateId);
+ }
+ return iface;
+ }
+
+ public static void handleTunnelMonitoringUpdates(AlivenessMonitorService alivenessMonitorService, DataBroker dataBroker,
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
+ Interface.OperStatus operStatus, boolean opStateModified){
+ // start/stop monitoring based on opState
+ if(!modifyTunnel(iface, opStateModified)){
+ return;
+ }
+
+ LOG.debug("handling tunnel monitoring updates for {} due to opstate modification", iface.getName());
+ if (operStatus == Interface.OperStatus.Down)
+ AlivenessMonitorUtils.stopLLDPMonitoring(alivenessMonitorService, dataBroker, iface);
+ else
+ AlivenessMonitorUtils.startLLDPMonitoring(alivenessMonitorService, dataBroker, iface);
+ }
+
+ public static boolean modifyOpState(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
+ boolean opStateModified){
+ return (opStateModified && (iface == null || iface != null && iface.isEnabled()));
+ }
+
+ public static boolean modifyIngressFlow(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
+ boolean opStateModified){
+ return modifyOpState(iface, opStateModified) && iface != null && iface.getAugmentation(IfTunnel.class) == null;
+ }
+
+ public static boolean modifyTunnel(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
+ boolean opStateModified){
+ return modifyOpState(iface, opStateModified) && iface != null && iface.getAugmentation(IfTunnel.class) != null;
+ }
+
+ public static void handleVlanIngressFlowUpdates(DataBroker dataBroker, Interface.OperStatus opState, WriteTransaction transaction,
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
+ NodeConnectorId nodeConnectorId, InstanceIdentifier<Interface> ifStateId){
+ LOG.debug("handling vlan ingress flow updates for {}", iface.getName());
+ Interface ifState = InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(ifStateId, dataBroker);
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ if (opState == org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Up) {
+ long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
+ List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, iface);
+ FlowBasedServicesUtils.installVlanFlow(dpId, portNo, iface, transaction, matches, ifState.getIfIndex());
+ } else {
+ FlowBasedServicesUtils.removeIngressFlow(iface.getName(), dpId, transaction);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.interfacemgr.renderer.ovs.statehelpers;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.utilities.SouthboundUtils;
+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.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+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 OvsInterfaceTopologyStateAddHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceTopologyStateAddHelper.class);
+ public static List<ListenableFuture<Void>> addPortToBridge(InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid,
+ OvsdbBridgeAugmentation bridgeNew, DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+
+ if (bridgeNew.getDatapathId() == null) {
+ LOG.warn("DataPathId found as null for Bridge Augmentation: {}... returning...", bridgeNew);
+ return futures;
+ }
+ BigInteger dpnId = IfmUtil.getDpnId(bridgeNew.getDatapathId());
+
+ // create bridge reference entry in interface meta operational DS
+ InterfaceMetaUtils.createBridgeRefEntry(dpnId, bridgeIid, writeTransaction);
+
+ // handle pre-provisioning of tunnels for the newly connected dpn
+ BridgeEntry bridgeEntry = InterfaceMetaUtils.getBridgeEntryFromConfigDS(dpnId, dataBroker);
+ if (bridgeEntry == null) {
+ LOG.debug("Bridge entry not found in config DS for dpn: {}", dpnId);
+ futures.add(writeTransaction.submit());
+ return futures;
+ }
+ SouthboundUtils.addAllPortsToBridge(bridgeEntry, dataBroker, bridgeIid, bridgeNew, writeTransaction);
+
+ futures.add(writeTransaction.submit());
+ return futures;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.interfacemgr.renderer.ovs.statehelpers;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.utilities.SouthboundUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryKey;
+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 OvsInterfaceTopologyStateRemoveHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceTopologyStateRemoveHelper.class);
+
+ public static List<ListenableFuture<Void>> removePortFromBridge(InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid,
+ OvsdbBridgeAugmentation bridgeOld, DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();;
+ BigInteger dpnId = IfmUtil.getDpnId(bridgeOld.getDatapathId());
+
+ if (dpnId == null) {
+ LOG.warn("Got Null DPID for Bridge: {}", bridgeOld);
+ return futures;
+ }
+
+ //delete bridge reference entry in interface meta operational DS
+ InterfaceMetaUtils.deleteBridgeRefEntry(dpnId, transaction);
+
+ futures.add(transaction.submit());
+ return futures;
+ }
+}
\ 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.interfacemgr.renderer.ovs.statehelpers;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.utilities.SouthboundUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfdStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntry;
+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 OvsInterfaceTopologyStateUpdateHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(OvsInterfaceTopologyStateUpdateHelper.class);
+ /*
+ * This code is used to handle only a dpnId change scenario for a particular change,
+ * which is not expected to happen in usual cases.
+ */
+ public static List<ListenableFuture<Void>> updateBridgeRefEntry(InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid,
+ OvsdbBridgeAugmentation bridgeNew,
+ OvsdbBridgeAugmentation bridgeOld,
+ DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction writeTransaction = dataBroker.newWriteOnlyTransaction();
+
+ BigInteger dpnIdNew = IfmUtil.getDpnId(bridgeNew.getDatapathId());
+ BigInteger dpnIdOld = IfmUtil.getDpnId(bridgeOld.getDatapathId());
+
+ //delete bridge reference entry for the old dpn in interface meta operational DS
+ InterfaceMetaUtils.deleteBridgeRefEntry(dpnIdOld, writeTransaction);
+
+ // create bridge reference entry in interface meta operational DS
+ InterfaceMetaUtils.createBridgeRefEntry(dpnIdNew, bridgeIid, writeTransaction);
+
+ // handle pre-provisioning of tunnels for the newly connected dpn
+ BridgeEntry bridgeEntry = InterfaceMetaUtils.getBridgeEntryFromConfigDS(dpnIdNew, dataBroker);
+ if (bridgeEntry == null) {
+ futures.add(writeTransaction.submit());
+ return futures;
+ }
+ SouthboundUtils.addAllPortsToBridge(bridgeEntry, dataBroker, bridgeIid, bridgeNew, writeTransaction);
+
+ futures.add(writeTransaction.submit());
+ return futures;
+ }
+
+ public static List<ListenableFuture<Void>> updateTunnelState(DataBroker dataBroker,
+ OvsdbTerminationPointAugmentation terminationPointNew,
+ OvsdbTerminationPointAugmentation terminationPointOld) {
+ List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
+
+ if (InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(terminationPointNew.getName(), dataBroker) == null) {
+ return futures;
+ }
+ // update opstate of interface if TEP has gone down/up as a result of BFD monitoring
+ LOG.debug("updating tunnel state for interface {}", terminationPointNew.getName());
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+ InterfaceManagerCommonUtils.updateOpState(transaction, terminationPointNew.getName(), getTunnelOpState(terminationPointNew.getInterfaceBfdStatus()));
+ futures.add(transaction.submit());
+ return futures;
+ }
+
+ private static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus
+ getTunnelOpState(List<InterfaceBfdStatus> tunnelBfdStatus) {
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus
+ livenessState = org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
+ if (tunnelBfdStatus != null && !tunnelBfdStatus.isEmpty()) {
+ for (InterfaceBfdStatus bfdState : tunnelBfdStatus) {
+ if (bfdState.getBfdStatusKey().equalsIgnoreCase(SouthboundUtils.BFD_OP_STATE)) {
+ String bfdOpState = bfdState.getBfdStatusValue();
+ if (bfdOpState.equalsIgnoreCase(SouthboundUtils.BFD_STATE_UP)) {
+ livenessState = org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Up;
+ } else {
+ livenessState = org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Down;
+ }
+ break;
+ }
+ }
+ }
+ return livenessState;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.interfacemgr.renderer.ovs.utilities;
+
+import com.google.common.collect.Maps;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+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.inet.types.rev100924.Uri;
+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.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.*;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.utilities.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class SouthboundUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(SouthboundUtils.class);
+
+ public static final String BFD_PARAM_ENABLE = "enable";
+ public static final String BFD_PARAM_INTERVAL = "min_tx";
+ // bfd params
+ public static final String BFD_OP_STATE = "state";
+ public static final String BFD_STATE_UP = "up";
+
+ public static final TopologyId OVSDB_TOPOLOGY_ID = new TopologyId(new Uri("ovsdb:1"));
+
+ public static void addPortToBridge(InstanceIdentifier<?> bridgeIid, Interface iface,
+ OvsdbBridgeAugmentation bridgeAugmentation, String bridgeName,
+ String portName, DataBroker dataBroker, List<ListenableFuture<Void>> futures) {
+ WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+ IfTunnel ifTunnel = iface.getAugmentation(IfTunnel.class);
+ if (ifTunnel != null) {
+ addTunnelPortToBridge(ifTunnel, bridgeIid, iface, bridgeAugmentation, bridgeName, portName, dataBroker, tx);
+ }
+ futures.add(tx.submit());
+ }
+
+ /*
+ * add all tunnels ports corresponding to the bridge to the topology config DS
+ */
+ public static void addAllPortsToBridge(BridgeEntry bridgeEntry, DataBroker dataBroker,
+ InstanceIdentifier<OvsdbBridgeAugmentation> bridgeIid,
+ OvsdbBridgeAugmentation bridgeNew,
+ WriteTransaction writeTransaction){
+ String bridgeName = bridgeNew.getBridgeName().getValue();
+ LOG.debug("adding all ports to bridge: {}", bridgeName);
+ List<BridgeInterfaceEntry> bridgeInterfaceEntries = bridgeEntry.getBridgeInterfaceEntry();
+ for (BridgeInterfaceEntry bridgeInterfaceEntry : bridgeInterfaceEntries) {
+ String portName = bridgeInterfaceEntry.getInterfaceName();
+ InterfaceKey interfaceKey = new InterfaceKey(portName);
+ Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+ IfTunnel ifTunnel = iface.getAugmentation(IfTunnel.class);
+ if (ifTunnel != null) {
+ addTunnelPortToBridge(ifTunnel, bridgeIid, iface, bridgeNew, bridgeName, portName, dataBroker, writeTransaction);
+ }
+ }
+ }
+
+ private static void addVlanPortToBridge(InstanceIdentifier<?> bridgeIid, IfL2vlan ifL2vlan, IfTunnel ifTunnel,
+ OvsdbBridgeAugmentation bridgeAugmentation, String bridgeName,
+ String portName, DataBroker dataBroker, WriteTransaction t) {
+ if(ifL2vlan.getVlanId() != null) {
+ addTerminationPoint(bridgeIid, bridgeAugmentation, bridgeName, portName, ifL2vlan.getVlanId().getValue(), null, null,
+ ifTunnel, t);
+ }
+ }
+
+ private static void addTunnelPortToBridge(IfTunnel ifTunnel, InstanceIdentifier<?> bridgeIid, Interface iface,
+ OvsdbBridgeAugmentation bridgeAugmentation, String bridgeName,
+ String portName, DataBroker dataBroker, WriteTransaction t) {
+ Class type = null;
+ LOG.debug("adding tunnel port {} to bridge {}",portName, bridgeName);
+
+ if (ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeGre.class) ||
+ ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeMplsOverGre.class)) {
+ type = InterfaceTypeGre.class;
+ } else if (ifTunnel.getTunnelInterfaceType().isAssignableFrom(TunnelTypeVxlan.class)) {
+ type = InterfaceTypeVxlan.class;
+ }
+
+ if (type == null) {
+ LOG.warn("Unknown Tunnel Type obtained while creating interface: {}", iface);
+ return;
+ }
+
+ int vlanId = 0;
+ IfL2vlan ifL2vlan = iface.getAugmentation(IfL2vlan.class);
+ if (ifL2vlan != null && ifL2vlan.getVlanId() != null) {
+ vlanId = ifL2vlan.getVlanId().getValue();
+ }
+
+ Map<String, String> options = Maps.newHashMap();
+ if(!ifTunnel.getTunnelInterfaceType().equals(TunnelTypeMplsOverGre.class) ) {
+ options.put("key", "flow");
+ }
+
+ IpAddress localIp = ifTunnel.getTunnelSource();
+ options.put("local_ip", localIp.getIpv4Address().getValue());
+
+ IpAddress remoteIp = ifTunnel.getTunnelDestination();
+ options.put("remote_ip", remoteIp.getIpv4Address().getValue());
+
+ addTerminationPoint(bridgeIid, bridgeAugmentation, bridgeName, portName, vlanId, type, options, ifTunnel, t);
+ }
+
+ // Update is allowed only for tunnel monitoring attributes
+ public static void updateBfdParamtersForTerminationPoint(InstanceIdentifier<?> bridgeIid, IfTunnel ifTunnel, String portName,
+ WriteTransaction transaction){
+ if( !ifTunnel.isInternal() && ifTunnel.getTunnelInterfaceType().equals(TunnelTypeVxlan.class) ) {
+ InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(
+ InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), portName);
+ LOG.debug("update bfd parameters for interface {}", tpIid);
+ OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
+ List<InterfaceBfd> bfdParams = getBfdParams(ifTunnel);
+ tpAugmentationBuilder.setInterfaceBfd(bfdParams);
+
+ TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
+ tpBuilder.setKey(InstanceIdentifier.keyOf(tpIid));
+ tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
+
+ transaction.merge(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build(), true);
+ }
+ }
+
+ private static void addTerminationPoint(InstanceIdentifier<?> bridgeIid, OvsdbBridgeAugmentation bridgeNode, String bridgeName, String portName, int vlanId, Class type,
+ Map<String, String> options, IfTunnel ifTunnel, WriteTransaction t) {
+ InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(
+ InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), portName);
+ OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
+
+ tpAugmentationBuilder.setName(portName);
+
+ if (type != null) {
+ tpAugmentationBuilder.setInterfaceType(type);
+ }
+
+ if (options != null) {
+ List<Options> optionsList = new ArrayList<Options>();
+ for (Map.Entry<String, String> entry : options.entrySet()) {
+ OptionsBuilder optionsBuilder = new OptionsBuilder();
+ optionsBuilder.setKey(new OptionsKey(entry.getKey()));
+ optionsBuilder.setOption(entry.getKey());
+ optionsBuilder.setValue(entry.getValue());
+ optionsList.add(optionsBuilder.build());
+ }
+ tpAugmentationBuilder.setOptions(optionsList);
+ }
+
+ if (vlanId != 0) {
+ tpAugmentationBuilder.setVlanMode(OvsdbPortInterfaceAttributes.VlanMode.Access);
+ tpAugmentationBuilder.setVlanTag(new VlanId(vlanId));
+ }
+
+
+ if( !ifTunnel.isInternal() && ifTunnel.getTunnelInterfaceType().equals(TunnelTypeVxlan.class) ) {
+ List<InterfaceBfd> bfdParams = getBfdParams(ifTunnel);
+ tpAugmentationBuilder.setInterfaceBfd(bfdParams);
+ }
+
+ TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
+ tpBuilder.setKey(InstanceIdentifier.keyOf(tpIid));
+ tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
+
+ t.put(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build(), true);
+
+ }
+
+ private static List<InterfaceBfd> getBfdParams(IfTunnel ifTunnel) {
+ List<InterfaceBfd> bfdParams = new ArrayList<>();
+ bfdParams.add(getIfBfdObj(BFD_PARAM_ENABLE,
+ Boolean.toString(ifTunnel.isMonitorEnabled())));
+ bfdParams.add(getIfBfdObj(BFD_PARAM_INTERVAL,
+ ifTunnel.getMonitorInterval().toString()));
+ return bfdParams;
+ }
+
+ private static InterfaceBfd getIfBfdObj(String key, String value) {
+ InterfaceBfdBuilder bfdBuilder = new InterfaceBfdBuilder();
+ bfdBuilder.setBfdKey(key).
+ setKey(new InterfaceBfdKey(key)).setBfdValue(value);
+ return bfdBuilder.build();
+ }
+
+ public static InstanceIdentifier<TerminationPoint> createTerminationPointInstanceIdentifier(NodeKey nodekey,
+ String portName){
+ InstanceIdentifier<TerminationPoint> terminationPointPath = InstanceIdentifier
+ .create(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
+ .child(Node.class,nodekey)
+ .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
+
+ LOG.debug("Termination point InstanceIdentifier generated : {}",terminationPointPath);
+ return terminationPointPath;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.renderer.ovs.utilities;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbPortInterfaceAttributes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Trunks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.TrunksBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class VlanTrunkSouthboundUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(VlanTrunkSouthboundUtils.class);
+ public static final TopologyId OVSDB_TOPOLOGY_ID = new TopologyId(new Uri("ovsdb:1"));
+
+ public static void addVlanPortToBridge(InstanceIdentifier<?> bridgeIid, IfL2vlan ifL2vlan,
+ OvsdbBridgeAugmentation bridgeAugmentation, String bridgeName,
+ String parentInterface, DataBroker dataBroker, WriteTransaction t) {
+ LOG.info("Vlan Interface creation not supported yet. please visit later.");
+ int vlanId = ifL2vlan.getVlanId().getValue();
+ addTrunkTerminationPoint(bridgeIid, bridgeAugmentation, bridgeName, parentInterface, vlanId, dataBroker, t);
+ }
+
+ public static void updateVlanMemberInTrunk(InstanceIdentifier<?> bridgeIid, IfL2vlan ifL2vlan,
+ OvsdbBridgeAugmentation bridgeAugmentation, String bridgeName,
+ String parentInterface, DataBroker dataBroker, WriteTransaction t) {
+ LOG.info("Vlan Interface creation not supported yet. please visit later.");
+ int vlanId = ifL2vlan.getVlanId().getValue();
+ updateTerminationPoint(bridgeIid, bridgeAugmentation, bridgeName, parentInterface, vlanId, dataBroker, t);
+ }
+
+ private static void addTrunkTerminationPoint(InstanceIdentifier<?> bridgeIid, OvsdbBridgeAugmentation bridgeNode,
+ String bridgeName, String parentInterface, int vlanId,
+ DataBroker dataBroker, WriteTransaction t) {
+ if (vlanId == 0) {
+ LOG.error("Found vlanid 0 for bridge: {}, interface: {}", bridgeName, parentInterface);
+ return;
+ }
+
+ InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(
+ InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), parentInterface);
+ OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
+ tpAugmentationBuilder.setName(parentInterface);
+ tpAugmentationBuilder.setVlanMode(OvsdbPortInterfaceAttributes.VlanMode.Trunk);
+ OvsdbTerminationPointAugmentation terminationPointAugmentation = null;
+ Optional<TerminationPoint> terminationPointOptional =
+ IfmUtil.read(LogicalDatastoreType.OPERATIONAL, tpIid, dataBroker);
+ if (terminationPointOptional.isPresent()) {
+ TerminationPoint terminationPoint = terminationPointOptional.get();
+ terminationPointAugmentation = terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
+ if (terminationPointAugmentation != null) {
+ List<Trunks> trunks = terminationPointAugmentation.getTrunks();
+ if (trunks == null) {
+ trunks = new ArrayList<>();
+ }
+
+ trunks.add(new TrunksBuilder().setTrunk(new VlanId(vlanId)).build());
+ tpAugmentationBuilder.setTrunks(trunks);
+ }
+ } else {
+ List<Trunks> trunks = new ArrayList<>();
+ trunks.add(new TrunksBuilder().setTrunk(new VlanId(vlanId)).build());
+ tpAugmentationBuilder.setTrunks(trunks);
+ }
+
+ TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
+ tpBuilder.setKey(InstanceIdentifier.keyOf(tpIid));
+ tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
+
+ t.put(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build(), true);
+ }
+
+ public static void addTerminationPointWithTrunks(InstanceIdentifier<?> bridgeIid, List<Trunks> trunks,
+ String parentInterface, WriteTransaction t) {
+ InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(
+ InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), parentInterface);
+ OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
+ tpAugmentationBuilder.setName(parentInterface);
+ tpAugmentationBuilder.setVlanMode(OvsdbPortInterfaceAttributes.VlanMode.Trunk);
+ tpAugmentationBuilder.setTrunks(trunks);
+
+ TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
+ tpBuilder.setKey(InstanceIdentifier.keyOf(tpIid));
+ tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
+
+ t.put(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build(), true);
+ }
+
+ private static void updateTerminationPoint(InstanceIdentifier<?> bridgeIid, OvsdbBridgeAugmentation bridgeNode,
+ String bridgeName, String parentInterface, int vlanId,
+ DataBroker dataBroker, WriteTransaction t) {
+ if (vlanId == 0) {
+ LOG.error("Found vlanid 0 for bridge: {}, interface: {}", bridgeName, parentInterface);
+ return;
+ }
+
+ InstanceIdentifier<TerminationPoint> tpIid = createTerminationPointInstanceIdentifier(
+ InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(Node.class)), parentInterface);
+ OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
+ tpAugmentationBuilder.setName(parentInterface);
+ tpAugmentationBuilder.setVlanMode(OvsdbPortInterfaceAttributes.VlanMode.Trunk);
+ OvsdbTerminationPointAugmentation terminationPointAugmentation = null;
+ Optional<TerminationPoint> terminationPointOptional =
+ IfmUtil.read(LogicalDatastoreType.OPERATIONAL, tpIid, dataBroker);
+ if (terminationPointOptional.isPresent()) {
+ TerminationPoint terminationPoint = terminationPointOptional.get();
+ terminationPointAugmentation = terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
+ if (terminationPointAugmentation != null) {
+ List<Trunks> trunks = terminationPointAugmentation.getTrunks();
+ if (trunks != null) {
+ trunks.remove(new TrunksBuilder().setTrunk(new VlanId(vlanId)).build());
+ }
+
+ tpAugmentationBuilder.setTrunks(trunks);
+ TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
+ tpBuilder.setKey(InstanceIdentifier.keyOf(tpIid));
+ tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
+
+ t.put(LogicalDatastoreType.CONFIGURATION, tpIid, tpBuilder.build(), true);
+ }
+ }
+ }
+
+ private static InstanceIdentifier<TerminationPoint> createTerminationPointInstanceIdentifier(NodeKey nodekey,
+ String portName){
+ InstanceIdentifier<TerminationPoint> terminationPointPath = InstanceIdentifier
+ .create(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
+ .child(Node.class,nodekey)
+ .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName)));
+
+ LOG.debug("Termination point InstanceIdentifier generated : {}", terminationPointPath);
+ return terminationPointPath;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.vpnservice.interfacemgr.rpcservice;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.ActionType;
+import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
+import org.opendaylight.vpnservice.mdsalutil.InstructionType;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+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.InterfaceType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
+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.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+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.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.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeMplsOverGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.*;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Future;
+
+public class InterfaceManagerRpcService implements OdlInterfaceRpcService {
+ private static final Logger LOG = LoggerFactory.getLogger(InterfaceManagerRpcService.class);
+ DataBroker dataBroker;
+ IMdsalApiManager mdsalMgr;
+
+
+ public InterfaceManagerRpcService(DataBroker dataBroker, IMdsalApiManager mdsalMgr) {
+ this.dataBroker = dataBroker;
+ this.mdsalMgr = mdsalMgr;
+ }
+
+ @Override
+ public Future<RpcResult<GetDpidFromInterfaceOutput>> getDpidFromInterface(GetDpidFromInterfaceInput input) {
+ String interfaceName = input.getIntfName();
+ RpcResultBuilder<GetDpidFromInterfaceOutput> rpcResultBuilder;
+ try {
+ BigInteger dpId = null;
+ InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
+ Interface interfaceInfo = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+ if (Tunnel.class.equals(interfaceInfo.getType())) {
+ ParentRefs parentRefs = interfaceInfo.getAugmentation(ParentRefs.class);
+ dpId = parentRefs.getDatapathNodeIdentifier();
+ } else {
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
+ InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceName, dataBroker);
+ String lowerLayerIf = ifState.getLowerLayerIf().get(0);
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
+ dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ }
+ GetDpidFromInterfaceOutputBuilder output = new GetDpidFromInterfaceOutputBuilder().setDpid(
+ (dpId));
+ rpcResultBuilder = RpcResultBuilder.success();
+ rpcResultBuilder.withResult(output.build());
+ } catch (Exception e) {
+ LOG.error("Retrieval of datapath id for the key {} failed due to {}", interfaceName, e);
+ rpcResultBuilder = RpcResultBuilder.failed();
+ }
+ return Futures.immediateFuture(rpcResultBuilder.build());
+ }
+
+ @Override
+ public Future<RpcResult<Void>> createTerminatingServiceActions(final CreateTerminatingServiceActionsInput input) {
+ final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+ try{
+ LOG.info("create terminatingServiceAction on DpnId = {} for tunnel-key {}", input.getDpid() , input.getTunnelKey());
+ Interface interfaceInfo = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(input.getInterfaceName()),dataBroker);
+ IfTunnel tunnelInfo = interfaceInfo.getAugmentation(IfTunnel.class);
+ if(tunnelInfo != null) {
+ ListenableFuture<Void> installFlowResult = (tunnelInfo.getTunnelInterfaceType().isAssignableFrom(TunnelTypeMplsOverGre.class)) ?
+ makeLFIBFlow(input.getDpid(),input.getTunnelKey(), input.getInstruction(), NwConstants.ADD_FLOW) :
+ makeTerminatingServiceFlow(tunnelInfo, input.getDpid(), input.getTunnelKey(), input.getInstruction(), NwConstants.ADD_FLOW);
+ Futures.addCallback(installFlowResult, new FutureCallback<Void>(){
+
+ @Override
+ public void onSuccess(Void aVoid) {
+ result.set(RpcResultBuilder.<Void>success().build());
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ String msg = String.format("Unable to install terminating service flow for %s", input.getInterfaceName());
+ LOG.error("create terminating service actions failed. {}. {}", msg, error);
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
+ }
+ });
+ result.set(RpcResultBuilder.<Void>success().build());
+ } else {
+ String msg = String.format("Terminating Service Actions cannot be created for a non-tunnel interface %s",input.getInterfaceName());
+ LOG.error(msg);
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg).build());
+ }
+ }catch(Exception e){
+ String msg = String.format("create Terminating Service Actions for %s failed",input.getInterfaceName());
+ LOG.error("create Terminating Service Actions for {} failed due to {}" ,input.getDpid(), e);
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, e.getMessage()).build());
+ }
+ return result;
+ }
+
+ @Override
+ public Future<RpcResult<Void>> removeTerminatingServiceActions(final RemoveTerminatingServiceActionsInput input) {
+ final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+ try{
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ LOG.info("remove terminatingServiceAction on DpnId = {} for tunnel-key {}", input.getDpid() , input.getTunnelKey());
+
+ Interface interfaceInfo = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(new InterfaceKey(input.getInterfaceName()),dataBroker);
+ IfTunnel tunnelInfo = interfaceInfo.getAugmentation(IfTunnel.class);
+ if(tunnelInfo != null) {
+ ListenableFuture<Void> removeFlowResult = (tunnelInfo.getTunnelInterfaceType().isAssignableFrom(TunnelTypeMplsOverGre.class)) ?
+ makeLFIBFlow(input.getDpid(),input.getTunnelKey(), null, NwConstants.DEL_FLOW) :
+ makeTerminatingServiceFlow(tunnelInfo, input.getDpid(), input.getTunnelKey(), null, NwConstants.DEL_FLOW);
+ Futures.addCallback(removeFlowResult, new FutureCallback<Void>(){
+
+ @Override
+ public void onSuccess(Void aVoid) {
+ result.set(RpcResultBuilder.<Void>success().build());
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ String msg = String.format("Unable to install terminating service flow %s", input.getInterfaceName());
+ LOG.error("create terminating service actions failed. {}. {}", msg, error);
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
+ }
+ });
+ result.set(RpcResultBuilder.<Void>success().build());
+ } else {
+ String msg = String.format("Terminating Service Actions cannot be removed for a non-tunnel interface %s",
+ input.getInterfaceName());
+ LOG.error(msg);
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg).build());
+ }
+ }catch(Exception e){
+ LOG.error("Remove Terminating Service Actions for {} failed due to {}" ,input.getDpid(), e);
+ String msg = String.format("Remove Terminating Service Actions for %d failed.", input.getDpid());
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, e.getMessage()).build());
+ }
+ return result;
+ }
+
+ @Override
+ public Future<RpcResult<GetEndpointIpForDpnOutput>> getEndpointIpForDpn(GetEndpointIpForDpnInput input) {
+ RpcResultBuilder<GetEndpointIpForDpnOutput> rpcResultBuilder;
+ try {
+ BridgeEntryKey bridgeEntryKey = new BridgeEntryKey(input.getDpid());
+ InstanceIdentifier<BridgeEntry> bridgeEntryInstanceIdentifier =
+ InterfaceMetaUtils.getBridgeEntryIdentifier(bridgeEntryKey);
+ BridgeEntry bridgeEntry =
+ InterfaceMetaUtils.getBridgeEntryFromConfigDS(bridgeEntryInstanceIdentifier,
+ dataBroker);
+ // local ip of any of the bridge interface entry will be the dpn end point ip
+ BridgeInterfaceEntry bridgeInterfaceEntry = bridgeEntry.getBridgeInterfaceEntry().get(0);
+ InterfaceKey interfaceKey = new InterfaceKey(bridgeInterfaceEntry.getInterfaceName());
+ Interface interfaceInfo = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+ IfTunnel tunnel = interfaceInfo.getAugmentation(IfTunnel.class);
+ GetEndpointIpForDpnOutputBuilder endpointIpForDpnOutput = new GetEndpointIpForDpnOutputBuilder().setLocalIps(Arrays.asList(tunnel.getTunnelSource()));
+ rpcResultBuilder = RpcResultBuilder.success();
+ rpcResultBuilder.withResult(endpointIpForDpnOutput.build());
+ }catch(Exception e){
+ LOG.error("Retrieval of endpoint of for dpn {} failed due to {}" ,input.getDpid(), e);
+ rpcResultBuilder = RpcResultBuilder.failed();
+ }
+ return Futures.immediateFuture(rpcResultBuilder.build());
+ }
+
+ @Override
+ public Future<RpcResult<GetEgressInstructionsForInterfaceOutput>> getEgressInstructionsForInterface(GetEgressInstructionsForInterfaceInput input) {
+ RpcResultBuilder<GetEgressInstructionsForInterfaceOutput> rpcResultBuilder;
+ try {
+ List<InstructionInfo> instructionInfo = new ArrayList<InstructionInfo>();
+ List<ActionInfo> actionInfo = IfmUtil.getEgressActionInfosForInterface(input.getIntfName(),
+ input.getTunnelKey(),
+ 0, /* ActionKey starting value */
+ dataBroker);
+ instructionInfo.add(new InstructionInfo(InstructionType.write_actions, actionInfo));
+ GetEgressInstructionsForInterfaceOutputBuilder output = new GetEgressInstructionsForInterfaceOutputBuilder().
+ setInstruction(buildInstructions(instructionInfo));
+ rpcResultBuilder = RpcResultBuilder.success();
+ rpcResultBuilder.withResult(output.build());
+ }catch(Exception e){
+ LOG.error("Retrieval of egress actions for the key {} failed due to {}" ,input.getIntfName(), e);
+ rpcResultBuilder = RpcResultBuilder.failed();
+ }
+ return Futures.immediateFuture(rpcResultBuilder.build());
+ }
+
+ @Override
+ public Future<RpcResult<GetInterfaceTypeOutput>> getInterfaceType(GetInterfaceTypeInput input) {
+ String interfaceName = input.getIntfName();
+ RpcResultBuilder<GetInterfaceTypeOutput> rpcResultBuilder;
+ try {
+ InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
+ Interface interfaceInfo = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+
+ GetInterfaceTypeOutputBuilder output = new GetInterfaceTypeOutputBuilder().setInterfaceType(interfaceInfo.getType());
+ rpcResultBuilder = RpcResultBuilder.success();
+ rpcResultBuilder.withResult(output.build());
+ } catch (Exception e) {
+ LOG.error("Retrieval of interface type for the key {} failed due to {}", interfaceName, e);
+ rpcResultBuilder = RpcResultBuilder.failed();
+ }
+ return Futures.immediateFuture(rpcResultBuilder.build());
+ }
+
+ @Override
+ public Future<RpcResult<GetTunnelTypeOutput>> getTunnelType(GetTunnelTypeInput input) {
+ String interfaceName = input.getIntfName();
+ RpcResultBuilder<GetTunnelTypeOutput> rpcResultBuilder;
+ try {
+ InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
+ Interface interfaceInfo = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+
+ if (Tunnel.class.equals(interfaceInfo.getType())) {
+ IfTunnel tnl = interfaceInfo.getAugmentation(IfTunnel.class);
+ Class <? extends TunnelTypeBase> tun_type = tnl.getTunnelInterfaceType();
+ GetTunnelTypeOutputBuilder output = new GetTunnelTypeOutputBuilder().setTunnelType(tun_type);
+ rpcResultBuilder = RpcResultBuilder.success();
+ rpcResultBuilder.withResult(output.build());
+ } else {
+ LOG.error("Retrieval of interface type for the key {} failed", interfaceName);
+ rpcResultBuilder = RpcResultBuilder.failed();
+ }
+ } catch (Exception e) {
+ LOG.error("Retrieval of interface type for the key {} failed due to {}", interfaceName, e);
+ rpcResultBuilder = RpcResultBuilder.failed();
+ }
+ return Futures.immediateFuture(rpcResultBuilder.build());
+ }
+
+ @Override
+ public Future<RpcResult<GetEgressActionsForInterfaceOutput>> getEgressActionsForInterface(GetEgressActionsForInterfaceInput input) {
+ RpcResultBuilder<GetEgressActionsForInterfaceOutput> rpcResultBuilder;
+ try {
+ LOG.debug("Get Egress Action for interface {} with key {}", input.getIntfName(), input.getTunnelKey());
+ List<Action> actionsList = IfmUtil.getEgressActionsForInterface(input.getIntfName(),
+ input.getTunnelKey(),
+ dataBroker);
+ GetEgressActionsForInterfaceOutputBuilder output = new GetEgressActionsForInterfaceOutputBuilder().
+ setAction(actionsList);
+ rpcResultBuilder = RpcResultBuilder.success();
+ rpcResultBuilder.withResult(output.build());
+ }catch(Exception e){
+ LOG.error("Retrieval of egress actions for the key {} failed due to {}" ,input.getIntfName(), e);
+ rpcResultBuilder = RpcResultBuilder.failed();
+ }
+ return Futures.immediateFuture(rpcResultBuilder.build());
+ }
+
+
+ @Override
+ public Future<RpcResult<GetPortFromInterfaceOutput>> getPortFromInterface(GetPortFromInterfaceInput input) {
+ RpcResultBuilder<GetPortFromInterfaceOutput> rpcResultBuilder;
+ String interfaceName = input.getIntfName();
+ try {
+ BigInteger dpId = null;
+ long portNo = 0;
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
+ InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceName, dataBroker);
+ String lowerLayerIf = ifState.getLowerLayerIf().get(0);
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
+ dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
+ // FIXME Assuming portName and interfaceName are same
+ GetPortFromInterfaceOutputBuilder output = new GetPortFromInterfaceOutputBuilder().setDpid(dpId).
+ setPortname(interfaceName).setPortno(Long.valueOf(portNo));
+ rpcResultBuilder = RpcResultBuilder.success();
+ rpcResultBuilder.withResult(output.build());
+ }catch(Exception e){
+ LOG.error("Retrieval of lport tag for the key {} failed due to {}" ,input.getIntfName(), e);
+ rpcResultBuilder = RpcResultBuilder.failed();
+ }
+ return Futures.immediateFuture(rpcResultBuilder.build());
+ }
+
+ @Override
+ public Future<RpcResult<GetNodeconnectorIdFromInterfaceOutput>> getNodeconnectorIdFromInterface(GetNodeconnectorIdFromInterfaceInput input) {
+ String interfaceName = input.getIntfName();
+ RpcResultBuilder<GetNodeconnectorIdFromInterfaceOutput> rpcResultBuilder;
+ try {
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
+ InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceName, dataBroker);
+ String lowerLayerIf = ifState.getLowerLayerIf().get(0);
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
+
+ GetNodeconnectorIdFromInterfaceOutputBuilder output = new GetNodeconnectorIdFromInterfaceOutputBuilder().setNodeconnectorId(nodeConnectorId);
+ rpcResultBuilder = RpcResultBuilder.success();
+ rpcResultBuilder.withResult(output.build());
+ } catch (Exception e) {
+ LOG.error("Retrieval of nodeconnector id for the key {} failed due to {}", interfaceName, e);
+ rpcResultBuilder = RpcResultBuilder.failed();
+ }
+ return Futures.immediateFuture(rpcResultBuilder.build());
+ }
+
+ @Override
+ public Future<RpcResult<GetInterfaceFromIfIndexOutput>> getInterfaceFromIfIndex(GetInterfaceFromIfIndexInput input) {
+ Integer ifIndex = input.getIfIndex();
+ RpcResultBuilder<GetInterfaceFromIfIndexOutput> rpcResultBuilder = null;
+ try {
+ InstanceIdentifier<IfIndexInterface> id = InstanceIdentifier.builder(IfIndexesInterfaceMap.class).child(IfIndexInterface.class, new IfIndexInterfaceKey(ifIndex)).build();
+ Optional<IfIndexInterface> ifIndexesInterface = IfmUtil.read(LogicalDatastoreType.OPERATIONAL, id, dataBroker);
+ if(ifIndexesInterface.isPresent()) {
+ String interfaceName = ifIndexesInterface.get().getInterfaceName();
+ GetInterfaceFromIfIndexOutputBuilder output = new GetInterfaceFromIfIndexOutputBuilder().setInterfaceName(interfaceName);
+ rpcResultBuilder = RpcResultBuilder.success();
+ rpcResultBuilder.withResult(output.build());
+ }
+ } catch (Exception e) {
+ LOG.error("Retrieval of interfaceName for the key {} failed due to {}", ifIndex, e);
+ rpcResultBuilder = RpcResultBuilder.failed();
+ }
+ return Futures.immediateFuture(rpcResultBuilder.build());
+ }
+
+ protected static List<Instruction> buildInstructions(List<InstructionInfo> listInstructionInfo) {
+ if (listInstructionInfo != null) {
+ List<Instruction> instructions = new ArrayList<Instruction>();
+ int instructionKey = 0;
+
+ for (InstructionInfo instructionInfo : listInstructionInfo) {
+ instructions.add(instructionInfo.buildInstruction(instructionKey));
+ instructionKey++;
+ }
+ return instructions;
+ }
+
+ return null;
+ }
+
+ private ListenableFuture<Void> makeTerminatingServiceFlow(IfTunnel tunnelInfo, BigInteger dpnId, BigInteger tunnelKey, List<Instruction> instruction, int addOrRemove) {
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {tunnelKey}));
+ short tableId = tunnelInfo.isInternal() ? NwConstants.INTERNAL_TUNNEL_TABLE :
+ NwConstants.EXTERNAL_TUNNEL_TABLE;
+ final String flowRef = getFlowRef(dpnId,tableId, tunnelKey);
+ Flow terminatingSerFlow = MDSALUtil.buildFlowNew(tableId, flowRef,
+ 5, "TST Flow Entry", 0, 0,
+ IfmConstants.TUNNEL_TABLE_COOKIE.add(tunnelKey), mkMatches, instruction);
+ if (addOrRemove == NwConstants.ADD_FLOW) {
+ return mdsalMgr.installFlow(dpnId, terminatingSerFlow);
+ }
+
+ return mdsalMgr.removeFlow(dpnId, terminatingSerFlow);
+ }
+
+ private ListenableFuture<Void> makeLFIBFlow(BigInteger dpnId, BigInteger tunnelKey, List<Instruction> instruction, int addOrRemove) {
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ mkMatches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[]{0x8847L}));
+ mkMatches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(tunnelKey.longValue())}));
+ // Install the flow entry in L3_LFIB_TABLE
+ String flowRef = getFlowRef(dpnId, NwConstants.L3_LFIB_TABLE, tunnelKey);
+
+ Flow lfibFlow = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
+ IfmConstants.DEFAULT_FLOW_PRIORITY, "LFIB Entry", 0, 0,
+ IfmConstants.COOKIE_VM_LFIB_TABLE, mkMatches, instruction);
+ if (addOrRemove == NwConstants.ADD_FLOW) {
+ return mdsalMgr.installFlow(dpnId, lfibFlow);
+ }
+ return mdsalMgr.removeFlow(dpnId, lfibFlow);
+ }
+
+ private String getFlowRef(BigInteger dpnId, short tableId, BigInteger tunnelKey) {
+ return new StringBuffer().append(IfmConstants.TUNNEL_TABLE_FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
+ .append(tableId).append(NwConstants.FLOWID_SEPARATOR).append(tunnelKey).toString();
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.servicebindings.flowbased.confighelpers;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+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.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.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.services.info.BoundServices;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class FlowBasedServicesConfigBindHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesConfigBindHelper.class);
+
+ public static List<ListenableFuture<Void>> bindService(InstanceIdentifier<BoundServices> instanceIdentifier,
+ BoundServices boundServiceNew, DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ String interfaceName =
+ InstanceIdentifier.keyOf(instanceIdentifier.firstIdentifierOf(ServicesInfo.class)).getInterfaceName();
+
+ 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 || ifState.getOperStatus() == OperStatus.Down) {
+ LOG.warn("Interface not up, not Binding Service for Interface: {}", interfaceName);
+ return futures;
+ }
+
+ // Get the Parent ServiceInfo
+
+ ServicesInfo servicesInfo = FlowBasedServicesUtils.getServicesInfoForInterface(interfaceName, dataBroker);
+ if (servicesInfo == null) {
+ LOG.error("Reached Impossible part 1 in the code during bind service for: {}", boundServiceNew);
+ return futures;
+ }
+
+ InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
+ Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+
+ List<BoundServices> allServices = servicesInfo.getBoundServices();
+ if (allServices.isEmpty()) {
+ LOG.error("Reached Impossible part 2 in the code during bind service for: {}", boundServiceNew);
+ return futures;
+ }
+
+ // Split based on type of interface....
+ if (iface.getType().isAssignableFrom(L2vlan.class)) {
+ return bindServiceOnVlan(boundServiceNew, allServices, iface, ifState.getIfIndex(), dataBroker);
+ } else if (iface.getType().isAssignableFrom(Tunnel.class)) {
+ return bindServiceOnTunnel(boundServiceNew, allServices, iface, ifState.getIfIndex(), dataBroker);
+ }
+ return futures;
+ }
+
+ private static List<ListenableFuture<Void>> bindServiceOnTunnel(BoundServices boundServiceNew, List<BoundServices> allServices, Interface iface, int ifIndex, DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
+ long portNo = Long.parseLong(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+
+ if (allServices.size() == 1) {
+ // If only one service present, install instructions in table 0.
+ List<MatchInfo> matches = null;
+ matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
+ FlowBasedServicesUtils.installInterfaceIngressFlow(dpId, iface, boundServiceNew,
+ transaction, matches, ifIndex, NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
+ if (transaction != null) {
+ futures.add(transaction.submit());
+ }
+ return futures;
+ }
+
+ boolean isCurrentServiceHighestPriority = true;
+ Map<Short, BoundServices> tmpServicesMap = new ConcurrentHashMap<>();
+ short highestPriority = 0xFF;
+ for (BoundServices boundService : allServices) {
+ if (boundService.getServicePriority() < boundServiceNew.getServicePriority()) {
+ isCurrentServiceHighestPriority = false;
+ break;
+ }
+ if (!boundService.equals(boundServiceNew)) {
+ tmpServicesMap.put(boundService.getServicePriority(), boundService);
+ if (boundService.getServicePriority() < highestPriority) {
+ highestPriority = boundService.getServicePriority();
+ }
+ }
+ }
+
+ if (!isCurrentServiceHighestPriority) {
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, boundServiceNew, iface, transaction,
+ ifIndex, boundServiceNew.getServicePriority(), (short) (boundServiceNew.getServicePriority()+1));
+ } else {
+ BoundServices serviceToReplace = tmpServicesMap.get(highestPriority);
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, serviceToReplace, iface, transaction,
+ ifIndex, boundServiceNew.getServicePriority(), (short) (boundServiceNew.getServicePriority()+1));
+ List<MatchInfo> matches = null;
+ matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
+
+ if (matches != null) {
+
+ WriteTransaction removeFlowTransaction = dataBroker.newWriteOnlyTransaction();
+ FlowBasedServicesUtils.removeIngressFlow(iface.getName(), serviceToReplace, dpId, removeFlowTransaction);
+ futures.add(removeFlowTransaction.submit());
+
+ WriteTransaction installFlowTransaction = dataBroker.newWriteOnlyTransaction();
+ FlowBasedServicesUtils.installInterfaceIngressFlow(dpId, iface, boundServiceNew, installFlowTransaction,
+ matches, ifIndex, NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
+ futures.add(installFlowTransaction.submit());
+ }
+ }
+
+ if (transaction != null) {
+ futures.add(transaction.submit());
+ }
+ return futures;
+ }
+
+ private static List<ListenableFuture<Void>> bindServiceOnVlan(BoundServices boundServiceNew, List<BoundServices> allServices, Interface iface, int ifIndex, DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+
+ if (allServices.size() == 1) {
+ //calling LportDispatcherTableForService with current service index as 0 and next service index as some value since this is the only service bound.
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, boundServiceNew, iface,
+ transaction, ifIndex, IfmConstants.DEFAULT_SERVICE_INDEX,(short) (boundServiceNew.getServicePriority() + 1));
+ if (transaction != null) {
+ futures.add(transaction.submit());
+ }
+ return futures;
+ }
+ allServices.remove(boundServiceNew);
+ BoundServices[] highLowPriorityService = FlowBasedServicesUtils.getHighAndLowPriorityService(allServices, boundServiceNew);
+ BoundServices low = highLowPriorityService[0];
+ BoundServices high = highLowPriorityService[1];
+ BoundServices highest = FlowBasedServicesUtils.getHighestPriorityService(allServices);
+ short currentServiceIndex = IfmConstants.DEFAULT_SERVICE_INDEX;
+ short nextServiceIndex = (short) (boundServiceNew.getServicePriority() + 1); // dummy service index
+ if (low != null) {
+ nextServiceIndex = low.getServicePriority();
+ if (low.equals(highest)) {
+ //In this case the match criteria of existing service should be changed.
+ BoundServices lower = FlowBasedServicesUtils.getHighAndLowPriorityService(allServices, low)[0];
+ short lowerServiceIndex = (short) ((lower!=null) ? lower.getServicePriority() : low.getServicePriority() + 1);
+ LOG.trace("Installing table 30 entry for existing service {} service match on service index {} update with service index {}", low, low.getServicePriority(), lowerServiceIndex);
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId,low, iface, transaction, ifIndex,low.getServicePriority(), lowerServiceIndex);
+ } else {
+ currentServiceIndex = boundServiceNew.getServicePriority();
+ }
+ }
+ if (high != null) {
+ currentServiceIndex = boundServiceNew.getServicePriority();
+ if (high.equals(highest)) {
+ LOG.trace("Installing table 30 entry for existing service {} service match on service index {} update with service index {}", high, IfmConstants.DEFAULT_SERVICE_INDEX, currentServiceIndex);
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, high, iface, transaction, ifIndex, IfmConstants.DEFAULT_SERVICE_INDEX, currentServiceIndex);
+ } else {
+ LOG.trace("Installing table 30 entry for existing service {} service match on service index {} update with service index {}", high, high.getServicePriority(), currentServiceIndex);
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, high, iface, transaction, ifIndex, high.getServicePriority(), currentServiceIndex);
+ }
+ }
+ LOG.trace("Installing table 30 entry for new service match on service index {} update with service index {}", currentServiceIndex, nextServiceIndex);
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, boundServiceNew, iface, transaction, ifIndex, currentServiceIndex, nextServiceIndex);
+ futures.add(transaction.submit());
+ return futures;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.confighelpers;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+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.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.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.services.info.BoundServices;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class FlowBasedServicesConfigUnbindHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesConfigUnbindHelper.class);
+
+ public static List<ListenableFuture<Void>> unbindService(InstanceIdentifier<BoundServices> instanceIdentifier,
+ BoundServices boundServiceOld, DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ String interfaceName =
+ InstanceIdentifier.keyOf(instanceIdentifier.firstIdentifierOf(ServicesInfo.class)).getInterfaceName();
+
+ // Get the Parent ServiceInfo
+ ServicesInfo servicesInfo = FlowBasedServicesUtils.getServicesInfoForInterface(interfaceName, dataBroker);
+ if (servicesInfo == null) {
+ LOG.error("Reached Impossible part in the code for bound service: {}", boundServiceOld);
+ return futures;
+ }
+
+ InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
+ Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+ 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 || ifState.getOperStatus() == OperStatus.Down) {
+ LOG.info("Not unbinding Service since operstatus is DOWN for Interface: {}", interfaceName);
+ return futures;
+ }
+ List<BoundServices> boundServices = servicesInfo.getBoundServices();
+
+ // Split based on type of interface....
+ if (iface.getType().isAssignableFrom(L2vlan.class)) {
+ return unbindServiceOnVlan(boundServiceOld, boundServices, iface, ifState.getIfIndex(), dataBroker);
+ } else if (iface.getType().isAssignableFrom(Tunnel.class)) {
+ return unbindServiceOnTunnel(boundServiceOld, boundServices, iface, ifState.getIfIndex(), dataBroker);
+ }
+ return futures;
+ }
+
+ private static List<ListenableFuture<Void>> unbindServiceOnVlan(
+ BoundServices boundServiceOld,
+ List<BoundServices> boundServices, Interface iface, int ifIndex,
+ DataBroker dataBroker) {
+
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ if (boundServices.isEmpty()) {
+ // Remove default entry from Lport Dispatcher Table.
+ FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface.getName(), boundServiceOld, t, IfmConstants.DEFAULT_SERVICE_INDEX);
+ if (t != null) {
+ futures.add(t.submit());
+ }
+ return futures;
+ }
+ BoundServices[] highLow = FlowBasedServicesUtils.getHighAndLowPriorityService(boundServices, boundServiceOld);
+ BoundServices low = highLow[0];
+ BoundServices high = highLow[1];
+ // This means the one removed was the highest priority service
+ if (high == null) {
+ LOG.trace("Deleting table entry for service {}, match service index {}", boundServiceOld, IfmConstants.DEFAULT_SERVICE_INDEX);
+ FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface.getName(), boundServiceOld, t, IfmConstants.DEFAULT_SERVICE_INDEX);
+ if (low != null) {
+ //delete the lower services flow entry.
+ LOG.trace("Deleting table entry for lower service {}, match service index {}", low, low.getServicePriority());
+ FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface.getName(), low, t, low.getServicePriority());
+ BoundServices lower = FlowBasedServicesUtils.getHighAndLowPriorityService(boundServices, low)[0];
+ short lowerServiceIndex = (short) ((lower!=null) ? lower.getServicePriority() : low.getServicePriority() + 1);
+ LOG.trace("Installing new entry for lower service {}, match service index {}, update service index {}", low, IfmConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, low, iface, t, ifIndex, IfmConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
+ }
+ } else {
+ LOG.trace("Deleting table entry for service {}, match service index {}", boundServiceOld, boundServiceOld.getServicePriority());
+ FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface.getName(), boundServiceOld, t, boundServiceOld.getServicePriority());
+ short lowerServiceIndex = (short) ((low!=null) ? low.getServicePriority() : boundServiceOld.getServicePriority() + 1);
+ BoundServices highest = FlowBasedServicesUtils.getHighestPriorityService(boundServices);
+ if (high.equals(highest)) {
+ LOG.trace("Update the existing higher service {}, match service index {}, update service index {}", high, IfmConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, high, iface, t, ifIndex, IfmConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
+ } else {
+ LOG.trace("Update the existing higher service {}, match service index {}, update service index {}", high, high.getServicePriority(), lowerServiceIndex);
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, high, iface, t, ifIndex, high.getServicePriority(), lowerServiceIndex);
+ }
+ }
+ futures.add(t.submit());
+ return futures;
+ }
+
+ private static List<ListenableFuture<Void>> unbindServiceOnTunnel(
+ BoundServices boundServiceOld,
+ List<BoundServices> boundServices, Interface iface, int ifIndex,
+ DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
+ long portNo = Long.parseLong(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+
+ if (boundServices.isEmpty()) {
+ // Remove entry from Ingress Table.
+ FlowBasedServicesUtils.removeIngressFlow(iface.getName(), boundServiceOld, dpId, t);
+ if (t != null) {
+ futures.add(t.submit());
+ }
+ return futures;
+ }
+
+ Map<Short, BoundServices> tmpServicesMap = new ConcurrentHashMap<>();
+ short highestPriority = 0xFF;
+ for (BoundServices boundService : boundServices) {
+ tmpServicesMap.put(boundService.getServicePriority(), boundService);
+ if (boundService.getServicePriority() < highestPriority) {
+ highestPriority = boundService.getServicePriority();
+ }
+ }
+
+ if (highestPriority < boundServiceOld.getServicePriority()) {
+ FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface.getName(), boundServiceOld, t, boundServiceOld.getServicePriority());
+ if (t != null) {
+ futures.add(t.submit());
+ }
+ return futures;
+ }
+
+ List<MatchInfo> matches = null;
+ matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
+
+ BoundServices toBeMoved = tmpServicesMap.get(highestPriority);
+ FlowBasedServicesUtils.removeIngressFlow(iface.getName(), boundServiceOld, dpId, t);
+ FlowBasedServicesUtils.installInterfaceIngressFlow(dpId, iface, toBeMoved, t,
+ matches, ifIndex, NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
+ FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface.getName(), toBeMoved, t, toBeMoved.getServicePriority());
+
+ if (t != null) {
+ futures.add(t.submit());
+ }
+ return futures;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.servicebindings.flowbased.listeners;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.vpnservice.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.confighelpers.FlowBasedServicesConfigBindHelper;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.confighelpers.FlowBasedServicesConfigUnbindHelper;
+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.service.bindings.ServicesInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+
+public class FlowBasedServicesConfigListener extends AsyncDataTreeChangeListenerBase<BoundServices, FlowBasedServicesConfigListener> {
+ private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesConfigListener.class);
+ private DataBroker dataBroker;
+
+ public FlowBasedServicesConfigListener(final DataBroker dataBroker) {
+ super(BoundServices.class, FlowBasedServicesConfigListener.class);
+ this.dataBroker = dataBroker;
+ }
+
+ @Override
+ protected InstanceIdentifier<BoundServices> getWildCardPath() {
+ return InstanceIdentifier.create(ServiceBindings.class).child(ServicesInfo.class)
+ .child(BoundServices.class);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<BoundServices> key, BoundServices boundServiceOld) {
+ String interfaceName = InstanceIdentifier.keyOf(key.firstIdentifierOf(ServicesInfo.class)).getInterfaceName();
+ LOG.info("Service Binding Entry removed for Interface: {}, Data: {}",
+ interfaceName, boundServiceOld);
+
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ RendererConfigRemoveWorker configWorker = new RendererConfigRemoveWorker(key, boundServiceOld);
+ coordinator.enqueueJob(interfaceName, configWorker);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<BoundServices> key, BoundServices boundServiceOld,
+ BoundServices boundServiceNew) {
+ LOG.error("Service Binding entry update not allowed for: {}, Data: {}",
+ InstanceIdentifier.keyOf(key.firstIdentifierOf(ServicesInfo.class)).getInterfaceName(), boundServiceNew);
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<BoundServices> key, BoundServices boundServicesNew) {
+ String interfaceName = InstanceIdentifier.keyOf(key.firstIdentifierOf(ServicesInfo.class)).getInterfaceName();
+ LOG.info("Service Binding Entry created for Interface: {}, Data: {}",
+ interfaceName, boundServicesNew);
+
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ RendererConfigAddWorker configWorker = new RendererConfigAddWorker(key, boundServicesNew);
+ coordinator.enqueueJob(interfaceName, configWorker);
+ }
+
+ @Override
+ protected FlowBasedServicesConfigListener getDataTreeChangeListener() {
+ return FlowBasedServicesConfigListener.this;
+ }
+
+ private class RendererConfigAddWorker implements Callable<List<ListenableFuture<Void>>> {
+ InstanceIdentifier<BoundServices> instanceIdentifier;
+ BoundServices boundServicesNew;
+
+ public RendererConfigAddWorker(InstanceIdentifier<BoundServices> instanceIdentifier,
+ BoundServices boundServicesNew) {
+ this.instanceIdentifier = instanceIdentifier;
+ this.boundServicesNew = boundServicesNew;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ return FlowBasedServicesConfigBindHelper.bindService(instanceIdentifier,
+ boundServicesNew, dataBroker);
+ }
+ }
+
+ private class RendererConfigRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
+ InstanceIdentifier<BoundServices> instanceIdentifier;
+ BoundServices boundServicesNew;
+
+ public RendererConfigRemoveWorker(InstanceIdentifier<BoundServices> instanceIdentifier,
+ BoundServices boundServicesNew) {
+ this.instanceIdentifier = instanceIdentifier;
+ this.boundServicesNew = boundServicesNew;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ return FlowBasedServicesConfigUnbindHelper.unbindService(instanceIdentifier,
+ boundServicesNew, dataBroker);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.servicebindings.flowbased.listeners;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.vpnservice.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.statehelpers.FlowBasedServicesStateBindHelper;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.statehelpers.FlowBasedServicesStateUnbindHelper;
+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.state.Interface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+
+public class FlowBasedServicesInterfaceStateListener extends AsyncDataTreeChangeListenerBase<Interface, FlowBasedServicesInterfaceStateListener> {
+ private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesInterfaceStateListener.class);
+ private DataBroker dataBroker;
+
+ public FlowBasedServicesInterfaceStateListener(final DataBroker dataBroker) {
+ super(Interface.class, FlowBasedServicesInterfaceStateListener.class);
+ this.dataBroker = dataBroker;
+ }
+
+ @Override
+ protected InstanceIdentifier<Interface> getWildCardPath() {
+ return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Interface> key, Interface interfaceStateOld) {
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ RendererStateInterfaceUnbindWorker stateUnbindWorker =
+ new RendererStateInterfaceUnbindWorker(interfaceStateOld);
+ coordinator.enqueueJob(interfaceStateOld.getName(), stateUnbindWorker);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Interface> key, Interface interfaceStateOld, Interface interfaceStateNew) {
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ if (interfaceStateNew.getOperStatus() == Interface.OperStatus.Down) {
+ RendererStateInterfaceUnbindWorker stateUnbindWorker =
+ new RendererStateInterfaceUnbindWorker(interfaceStateNew);
+ coordinator.enqueueJob(interfaceStateNew.getName(), stateUnbindWorker);
+ return;
+ }
+
+ RendererStateInterfaceBindWorker stateBindWorker = new RendererStateInterfaceBindWorker(interfaceStateNew);
+ coordinator.enqueueJob(interfaceStateNew.getName(), stateBindWorker);
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Interface> key, Interface interfaceStateNew) {
+ if (interfaceStateNew.getOperStatus() == Interface.OperStatus.Down) {
+ LOG.info("Interface: {} operstate is down when adding. Not Binding services", interfaceStateNew.getName());
+ return;
+ }
+
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ RendererStateInterfaceBindWorker stateBindWorker = new RendererStateInterfaceBindWorker(interfaceStateNew);
+ coordinator.enqueueJob(interfaceStateNew.getName(), stateBindWorker);
+ }
+
+ @Override
+ protected FlowBasedServicesInterfaceStateListener getDataTreeChangeListener() {
+ return FlowBasedServicesInterfaceStateListener.this;
+ }
+
+ private class RendererStateInterfaceBindWorker implements Callable<List<ListenableFuture<Void>>> {
+ Interface iface;
+
+ public RendererStateInterfaceBindWorker(Interface iface) {
+ this.iface = iface;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ return FlowBasedServicesStateBindHelper.bindServicesOnInterface(iface, dataBroker);
+ }
+ }
+
+ private class RendererStateInterfaceUnbindWorker implements Callable<List<ListenableFuture<Void>>> {
+ Interface iface;
+
+ public RendererStateInterfaceUnbindWorker(Interface iface) {
+ this.iface = iface;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ return FlowBasedServicesStateUnbindHelper.unbindServicesFromInterface(iface, dataBroker);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.servicebindings.flowbased.statehelpers;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+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.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+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.services.info.BoundServices;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public class FlowBasedServicesStateBindHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesStateBindHelper.class);
+
+ public static List<ListenableFuture<Void>> bindServicesOnInterface(Interface ifaceState,
+ DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ ServicesInfo servicesInfo = FlowBasedServicesUtils.getServicesInfoForInterface(ifaceState.getName(), dataBroker);
+ if (servicesInfo == null) {
+ return futures;
+ }
+
+ List<BoundServices> allServices = servicesInfo.getBoundServices();
+ if (allServices == null || allServices.isEmpty()) {
+ return futures;
+ }
+
+ InterfaceKey interfaceKey = new InterfaceKey(ifaceState.getName());
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
+ InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+
+ if (iface.getType().isAssignableFrom(L2vlan.class)) {
+ return bindServiceOnVlan(allServices, iface, ifaceState.getIfIndex(), dataBroker);
+ } else if (iface.getType().isAssignableFrom(Tunnel.class)){
+ return bindServiceOnTunnel(allServices, iface, ifaceState.getIfIndex(), dataBroker);
+ }
+ return futures;
+ }
+
+ private static List<ListenableFuture<Void>> bindServiceOnTunnel(
+ List<BoundServices> allServices,
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
+ Integer ifIndex, DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
+ long portNo = Long.parseLong(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
+ BoundServices highestPriorityBoundService = FlowBasedServicesUtils.getHighestPriorityService(allServices);
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ if (matches != null) {
+ FlowBasedServicesUtils.installInterfaceIngressFlow(dpId, iface, highestPriorityBoundService,
+ t, matches, ifIndex, NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
+ }
+
+ for (BoundServices boundService : allServices) {
+ if (!boundService.equals(highestPriorityBoundService)) {
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, boundService, iface, t, ifIndex, boundService.getServicePriority(), (short) (boundService.getServicePriority()+1));
+ }
+ }
+
+ futures.add(t.submit());
+ return futures;
+ }
+
+ private static List<ListenableFuture<Void>> bindServiceOnVlan(
+ List<BoundServices> allServices,
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
+ Integer ifIndex, DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ Collections.sort(allServices, new Comparator<BoundServices>() {
+ @Override
+ public int compare(BoundServices serviceInfo1, BoundServices serviceInfo2) {
+ return serviceInfo1.getServicePriority().compareTo(serviceInfo2.getServicePriority());
+ }
+ });
+ BoundServices highestPriority = allServices.remove(0);
+ short nextServiceIndex = (short) (allServices.size() > 0 ? allServices.get(0).getServicePriority() : highestPriority.getServicePriority() + 1);
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, highestPriority, iface, t, ifIndex, IfmConstants.DEFAULT_SERVICE_INDEX, nextServiceIndex);
+ BoundServices prev = null;
+ for (BoundServices boundService : allServices) {
+ if (prev!=null) {
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, prev, iface, t, ifIndex, prev.getServicePriority(), boundService.getServicePriority());
+ }
+ prev = boundService;
+ }
+ if (prev!=null) {
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, prev, iface, t, ifIndex, prev.getServicePriority(), (short) (prev.getServicePriority()+1));
+ }
+ futures.add(t.submit());
+ return futures;
+
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.servicebindings.flowbased.statehelpers;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+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.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+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.services.info.BoundServices;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class FlowBasedServicesStateUnbindHelper {
+ private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesStateUnbindHelper.class);
+
+ public static List<ListenableFuture<Void>> unbindServicesFromInterface(Interface ifaceState,
+ DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+
+ ServicesInfo servicesInfo = FlowBasedServicesUtils.getServicesInfoForInterface(ifaceState.getName(), dataBroker);
+ if (servicesInfo == null) {
+ return futures;
+ }
+
+ List<BoundServices> allServices = servicesInfo.getBoundServices();
+ if (allServices == null || allServices.isEmpty()) {
+ return futures;
+ }
+
+ if (ifaceState.getType().isAssignableFrom(L2vlan.class)) {
+ return unbindServiceOnVlan(allServices, ifaceState, ifaceState.getIfIndex(), dataBroker);
+ } else if (ifaceState.getType().isAssignableFrom(Tunnel.class)){
+ return unbindServiceOnTunnel(allServices, ifaceState, ifaceState.getIfIndex(), dataBroker);
+ }
+ return futures;
+ }
+
+ private static List<ListenableFuture<Void>> unbindServiceOnTunnel(
+ List<BoundServices> allServices,
+ Interface iface,
+ Integer ifIndex, DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+
+ List<String> ofportIds = iface.getLowerLayerIf();
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
+ if(nodeConnectorId == null){
+ return futures;
+ }
+ BoundServices highestPriorityBoundService = FlowBasedServicesUtils.getHighestPriorityService(allServices);
+
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ FlowBasedServicesUtils.removeIngressFlow(iface.getName(), highestPriorityBoundService, dpId, t);
+
+ for (BoundServices boundService : allServices) {
+ if (!boundService.equals(highestPriorityBoundService)) {
+ FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface.getName(), boundService, t, boundService.getServicePriority());
+ }
+ }
+
+ futures.add(t.submit());
+ return futures;
+ }
+
+ private static List<ListenableFuture<Void>> unbindServiceOnVlan(
+ List<BoundServices> allServices, Interface ifaceState,
+ Integer ifIndex, DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ List<String> ofportIds = ifaceState.getLowerLayerIf();
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
+ if(nodeConnectorId == null){
+ return futures;
+ }
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ Collections.sort(allServices, new Comparator<BoundServices>() {
+ @Override
+ public int compare(BoundServices serviceInfo1, BoundServices serviceInfo2) {
+ return serviceInfo1.getServicePriority().compareTo(serviceInfo2.getServicePriority());
+ }
+ });
+ BoundServices highestPriority = allServices.remove(0);
+ FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, ifaceState.getName(), highestPriority, t, IfmConstants.DEFAULT_SERVICE_INDEX);
+ for (BoundServices boundService : allServices) {
+ FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, ifaceState.getName(), boundService, t, boundService.getServicePriority());
+ }
+ futures.add(t.submit());
+ return futures;
+
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.servicebindings.flowbased.utilities;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+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.vpnservice.mdsalutil.NwConstants;
+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.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.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCase;
+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.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.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+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.StypeOpenflow;
+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.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.vpnservice.interfacemgr.rev150331.IfL2vlan;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class FlowBasedServicesUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesUtils.class);
+
+ public static ServicesInfo getServicesInfoForInterface(String interfaceName, DataBroker dataBroker) {
+ ServicesInfoKey servicesInfoKey = new ServicesInfoKey(interfaceName);
+ InstanceIdentifier.InstanceIdentifierBuilder<ServicesInfo> servicesInfoIdentifierBuilder =
+ InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class, servicesInfoKey);
+ Optional<ServicesInfo> servicesInfoOptional = IfmUtil.read(LogicalDatastoreType.CONFIGURATION,
+ servicesInfoIdentifierBuilder.build(), dataBroker);
+
+ if (servicesInfoOptional.isPresent()) {
+ return servicesInfoOptional.get();
+ }
+
+ return null;
+ }
+
+ public static NodeConnectorId getNodeConnectorIdFromInterface(Interface iface, DataBroker dataBroker) {
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
+ InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(iface.getName(), dataBroker);
+ if(ifState != null) {
+ List<String> ofportIds = ifState.getLowerLayerIf();
+ return new NodeConnectorId(ofportIds.get(0));
+ }
+ return null;
+ }
+
+ public static List<MatchInfo> getMatchInfoForVlanPortAtIngressTable(BigInteger dpId, long portNo, Interface iface) {
+ List<MatchInfo> matches = new ArrayList<>();
+ matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {dpId, BigInteger.valueOf(portNo)}));
+ int vlanId = 0;
+ IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
+ if(l2vlan != null && l2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Transparent){
+ vlanId = l2vlan.getVlanId() == null ? 0 : l2vlan.getVlanId().getValue();
+ }
+ if (vlanId > 0) {
+ matches.add(new MatchInfo(MatchFieldType.vlan_vid, new long[]{vlanId}));
+ }
+ return matches;
+ }
+
+ public static List<MatchInfo> getMatchInfoForTunnelPortAtIngressTable(BigInteger dpId, long portNo, Interface iface) {
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[]{dpId, BigInteger.valueOf(portNo)}));
+ return matches;
+ }
+
+ public static List<MatchInfo> getMatchInfoForDispatcherTable(BigInteger dpId, Interface iface,
+ int interfaceTag, short servicePriority) {
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ MetaDataUtil.getMetaDataForLPortDispatcher(interfaceTag, servicePriority),
+ MetaDataUtil.getMetaDataMaskForLPortDispatcher() }));
+ return matches;
+ }
+
+ public static Long getLPortTag(Interface iface, DataBroker dataBroker) {
+ /*ParentRefs parentRefs = iface.getAugmentation(ParentRefs.class);
+ String portName = parentRefs.getParentInterface();
+ BigInteger dpIdFromInterface = parentRefs.getDatapathNodeIdentifier();
+ String portKey = FlowBasedServicesUtils.getInterfaceRefInfo(dpIdFromInterface.toString(), portName);
+ if (iface.getType().isAssignableFrom(L2vlan.class)) {
+ InterfacesMetaKey interfacesMetaKey = new InterfacesMetaKey(portKey);
+ InterfacesInfoKey interfacesInfoKey = new InterfacesInfoKey(iface.getName());
+ InterfacesInfo interfacesInfo = VlanInterfaceUtilities.getInterfacesInfoFromConfigDS(interfacesMetaKey,
+ interfacesInfoKey, dataBroker);
+ return interfacesInfo.getLporttag();
+ } else if (iface.getType().isAssignableFrom(Tunnel.class)) {
+ TunnelInterfaceRefInfoKey tunnelInterfaceRefInfoKey = new TunnelInterfaceRefInfoKey(portKey);
+ TunnelInterfaceEntries tunnelInterfaceEntries =
+ TunnelInterfaceUtilities.getTunnelInterfaceRefEntriesFromConfigDs(
+ tunnelInterfaceRefInfoKey, iface.getName(), dataBroker);
+ return tunnelInterfaceEntries.getLportTag();
+ } */
+ return 0L;
+ }
+
+ public static void installInterfaceIngressFlow(BigInteger dpId, Interface iface,
+ BoundServices boundServiceNew,
+ WriteTransaction t,
+ List<MatchInfo> matches, int lportTag, short tableId) {
+ List<Instruction> instructions = boundServiceNew.getAugmentation(StypeOpenflow.class).getInstruction();
+
+ int serviceInstructionsSize = instructions.size();
+ List<Instruction> instructionSet = new ArrayList<Instruction>();
+ int vlanId = 0;
+ IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
+ if(l2vlan != null && l2vlan.getVlanId() != null){
+ vlanId = l2vlan.getVlanId().getValue();
+ }
+ if (vlanId != 0) {
+ // incrementing instructionSize and using it as actionKey. Because it won't clash with any other instructions
+ int actionKey = ++serviceInstructionsSize;
+ instructionSet.add(MDSALUtil.buildAndGetPopVlanActionInstruction(actionKey, ++serviceInstructionsSize));
+ }
+
+ if (lportTag != 0L) {
+ BigInteger[] metadataValues = IfmUtil.mergeOpenflowMetadataWriteInstructions(instructions);
+ short sIndex = boundServiceNew.getServicePriority();
+ BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lportTag,
+ ++sIndex, metadataValues[0]);
+ BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(
+ MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
+ MetaDataUtil.METADATA_MASK_LPORT_TAG, metadataValues[1]);
+ instructionSet.add(MDSALUtil.buildAndGetWriteMetadaInstruction(metadata, metadataMask,
+ ++serviceInstructionsSize));
+ }
+
+ if (instructions != null && !instructions.isEmpty()) {
+ for (Instruction info : instructions) {
+ // Skip meta data write as that is handled already
+ if (info.getInstruction() instanceof WriteMetadataCase) {
+ continue;
+ }
+ instructionSet.add(info);
+ }
+ }
+
+ String serviceRef = boundServiceNew.getServiceName();
+ String flowRef = getFlowRef(dpId, iface.getName(), boundServiceNew, boundServiceNew.getServicePriority());
+ StypeOpenflow stypeOpenflow = boundServiceNew.getAugmentation(StypeOpenflow.class);
+ Flow ingressFlow = MDSALUtil.buildFlowNew(tableId, flowRef,
+ stypeOpenflow.getFlowPriority(), serviceRef, 0, 0,
+ stypeOpenflow.getFlowCookie(), matches, instructionSet);
+ installFlow(dpId, ingressFlow, t);
+ }
+
+ public static void installFlow(BigInteger dpId, Flow flow, WriteTransaction t) {
+ FlowKey flowKey = new FlowKey(new FlowId(flow.getId()));
+ Node nodeDpn = buildInventoryDpnNode(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();
+
+ t.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flow, true);
+ }
+
+ public static void removeFlow(String flowRef, BigInteger dpId, WriteTransaction t) {
+ LOG.debug("Removing Ingress Flows");
+ FlowKey flowKey = new FlowKey(new FlowId(flowRef));
+ Node nodeDpn = buildInventoryDpnNode(dpId);
+ InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
+ .child(Table.class, new TableKey(NwConstants.VLAN_INTERFACE_INGRESS_TABLE)).child(Flow.class, flowKey).build();
+
+ t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
+ }
+
+ private static Node buildInventoryDpnNode(BigInteger dpnId) {
+ NodeId nodeId = new NodeId("openflow:" + dpnId);
+ Node nodeDpn = new NodeBuilder().setId(nodeId).setKey(new NodeKey(nodeId)).build();
+
+ return nodeDpn;
+ }
+
+ public static void installLPortDispatcherFlow(BigInteger dpId, BoundServices boundService, Interface iface,
+ WriteTransaction t, int interfaceTag, short currentServiceIndex, short nextServiceIndex) {
+ LOG.debug("Installing LPort Dispatcher Flows {}, {}", dpId, iface);
+ String serviceRef = boundService.getServiceName();
+ List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForDispatcherTable(dpId, iface,
+ interfaceTag, currentServiceIndex);
+
+ // Get the metadata and mask from the service's write metadata instruction
+ StypeOpenflow stypeOpenFlow = boundService.getAugmentation(StypeOpenflow.class);
+ List<Instruction> serviceInstructions = stypeOpenFlow.getInstruction();
+ int instructionSize = serviceInstructions.size();
+ BigInteger[] metadataValues = IfmUtil.mergeOpenflowMetadataWriteInstructions(serviceInstructions);
+ BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(interfaceTag, nextServiceIndex, metadataValues[0]);
+ BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
+ MetaDataUtil.METADATA_MASK_LPORT_TAG, metadataValues[1]);
+
+ // build the final instruction for LPort Dispatcher table flow entry
+ List<Instruction> instructions = new ArrayList<Instruction>();
+ instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(metadata, metadataMask, ++instructionSize));
+ if (serviceInstructions != null && !serviceInstructions.isEmpty()) {
+ for (Instruction info : serviceInstructions) {
+ // Skip meta data write as that is handled already
+ if (info.getInstruction() instanceof WriteMetadataCase) {
+ continue;
+ }
+ instructions.add(info);
+ }
+ }
+
+ // build the flow and install it
+ String flowRef = getFlowRef(dpId, iface.getName(), boundService, currentServiceIndex);
+ Flow ingressFlow = MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
+ boundService.getServicePriority(), serviceRef, 0, 0, stypeOpenFlow.getFlowCookie(), matches, instructions);
+ installFlow(dpId, ingressFlow, t);
+ }
+
+ public static void removeIngressFlow(String name, BoundServices serviceOld, BigInteger dpId, WriteTransaction t) {
+ LOG.debug("Removing Ingress Flows");
+ String flowKeyStr = getFlowRef(dpId, name, serviceOld, serviceOld.getServicePriority());
+ FlowKey flowKey = new FlowKey(new FlowId(flowKeyStr));
+ Node nodeDpn = buildInventoryDpnNode(dpId);
+ InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
+ .child(Table.class, new TableKey(NwConstants.VLAN_INTERFACE_INGRESS_TABLE)).child(Flow.class, flowKey).build();
+
+ t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
+ }
+
+ public static void removeLPortDispatcherFlow(BigInteger dpId, String iface, BoundServices boundServicesOld, WriteTransaction t, short currentServiceIndex) {
+ LOG.debug("Removing LPort Dispatcher Flows {}, {}", dpId, iface);
+
+ StypeOpenflow stypeOpenFlow = boundServicesOld.getAugmentation(StypeOpenflow.class);
+ // build the flow and install it
+ String flowRef = getFlowRef(dpId, iface, boundServicesOld, currentServiceIndex);
+ FlowKey flowKey = new FlowKey(new FlowId(flowRef));
+ Node nodeDpn = buildInventoryDpnNode(dpId);
+ InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
+ .child(Table.class, new TableKey(NwConstants.LPORT_DISPATCHER_TABLE)).child(Flow.class, flowKey).build();
+
+ t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
+ }
+
+ private static String getFlowRef(BigInteger dpnId, String iface, BoundServices service, short currentServiceIndex) {
+ return new StringBuffer().append(dpnId).append(NwConstants.VLAN_INTERFACE_INGRESS_TABLE).append(NwConstants.FLOWID_SEPARATOR)
+ .append(iface).append(NwConstants.FLOWID_SEPARATOR).append(currentServiceIndex).toString();
+ }
+
+ /**
+ * This util method returns an array of ServiceInfo in which index 0 will
+ * have the immediate lower priority service and index 1 will have the
+ * immediate higher priority service among the list of existing serviceInfos
+ *
+ * @param serviceInfos
+ * @param currentServiceInfo
+ * @return
+ */
+ public static BoundServices[] getHighAndLowPriorityService(
+ List<BoundServices> serviceInfos, BoundServices currentServiceInfo) {
+ BoundServices higher = null; // this will be used to hold the immediate higher service priority with respect to the currentServiceInfo
+ BoundServices lower = null; // this will be used to hold the immediate lower service priority with respect to the currentServiceInfo
+ if (serviceInfos == null || serviceInfos.isEmpty()) {
+ return new BoundServices[]{lower, higher};
+ }
+ List <BoundServices> availableServiceInfos = new ArrayList<BoundServices>(serviceInfos);
+ Collections.sort(availableServiceInfos, new Comparator<BoundServices>() {
+ @Override
+ public int compare(BoundServices serviceInfo1, BoundServices serviceInfo2) {
+ return serviceInfo1.getServicePriority().compareTo(serviceInfo2.getServicePriority());
+ }
+ });
+ for (BoundServices availableServiceInfo: availableServiceInfos) {
+ if (currentServiceInfo.getServicePriority() < availableServiceInfo.getServicePriority()) {
+ lower = availableServiceInfo;
+ break;
+ } else {
+ higher = availableServiceInfo;
+ }
+ }
+ return new BoundServices[]{lower,higher};
+ }
+
+ public static BoundServices getHighestPriorityService(List<BoundServices> serviceInfos) {
+ List <BoundServices> availableServiceInfos = new ArrayList<BoundServices>(serviceInfos);
+ if (availableServiceInfos.isEmpty()) {
+ return null;
+ }
+ BoundServices highPriorityService = availableServiceInfos.get(0);
+ availableServiceInfos.remove(0);
+ for (BoundServices availableServiceInfo: availableServiceInfos) {
+ if (availableServiceInfo.getServicePriority() < highPriorityService.getServicePriority()) {
+ highPriorityService = availableServiceInfo;
+ }
+ }
+ return highPriorityService;
+ }
+
+ public static void installVlanFlow(BigInteger dpId, long portNo, Interface iface,
+ WriteTransaction t, List<MatchInfo> matches, int lportTag) {
+ int vlanId = 0;
+ boolean isVlanTransparent = false;
+ IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
+ if(l2vlan != null){
+ vlanId = l2vlan.getVlanId() == null ? 0 : l2vlan.getVlanId().getValue();
+ isVlanTransparent = l2vlan.getL2vlanMode() == IfL2vlan.L2vlanMode.Transparent;
+ }
+ int instructionKey = 0;
+ BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lportTag, (short) 0);
+ BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher();
+ List<Instruction> instructions = new ArrayList<Instruction>();
+ if (vlanId != 0 && !isVlanTransparent) {
+ instructions.add(MDSALUtil.buildAndGetPopVlanActionInstruction(lportTag, instructionKey++));
+ }
+ instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(metadata, metadataMask, instructionKey++));
+ instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.DHCP_TABLE, instructionKey++));
+ int priority = isVlanTransparent ? 1 : vlanId == 0 ? IfmConstants.FLOW_PRIORITY_FOR_UNTAGGED_VLAN : IfmConstants.FLOW_HIGH_PRIORITY;
+ String flowRef = getFlowRef(IfmConstants.VLAN_INTERFACE_INGRESS_TABLE, dpId, iface.getName());
+ Flow ingressFlow = MDSALUtil.buildFlowNew(IfmConstants.VLAN_INTERFACE_INGRESS_TABLE, flowRef, priority, flowRef, 0, 0,
+ IfmConstants.VLAN_TABLE_COOKIE, matches, instructions);
+ installFlow(dpId, ingressFlow, t);
+}
+
+ public static String getFlowRef(short tableId, BigInteger dpnId, String infName) {
+ return String.format("%d:%s:%s", tableId, dpnId, infName);
+ }
+
+ public static void removeIngressFlow(String interfaceName, BigInteger dpId, WriteTransaction t) {
+ LOG.debug("Removing Ingress Flows");
+ String flowKeyStr = getFlowRef(IfmConstants.VLAN_INTERFACE_INGRESS_TABLE, dpId, interfaceName);
+ FlowKey flowKey = new FlowKey(new FlowId(flowKeyStr));
+ Node nodeDpn = buildInventoryDpnNode(dpId);
+ InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
+ .child(Table.class, new TableKey(NwConstants.VLAN_INTERFACE_INGRESS_TABLE)).child(Flow.class, flowKey).build();
+
+ t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
+ }
+
+
+}
--- /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.statusanddiag;
+
+import java.lang.management.ManagementFactory;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class InterfaceStatusMonitor implements InterfaceStatusMonitorMBean{
+
+ private String serviceStatus;
+ private static InterfaceStatusMonitor interfaceStatusMonitor = new InterfaceStatusMonitor();
+ private static final String JMX_INTERFACE_OBJ_NAME = "com.ericsson.sdncp.services.status:type=SvcInterfaceService";
+ private static final Logger log = LoggerFactory.getLogger(InterfaceStatusMonitor.class);
+
+ private InterfaceStatusMonitor () {
+ }
+
+ public void registerMbean() {
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ try {
+ ObjectName objName = new ObjectName(JMX_INTERFACE_OBJ_NAME);
+ log.debug("MXBean Object-Name framed");
+ mbs.registerMBean(interfaceStatusMonitor, objName);
+ log.info("MXBean registration SUCCESSFUL!!! {}", JMX_INTERFACE_OBJ_NAME);
+ } catch (InstanceAlreadyExistsException iaeEx) {
+ log.error("MXBean registration FAILED with InstanceAlreadyExistsException", iaeEx);
+ } catch (MBeanRegistrationException mbrEx) {
+ log.error("MXBean registration FAILED with MBeanRegistrationException", mbrEx);
+ } catch (NotCompliantMBeanException ncmbEx) {
+ log.error("MXBean registration FAILED with NotCompliantMBeanException", ncmbEx);
+ } catch (MalformedObjectNameException monEx) {
+ log.error("MXBean registration failed with MalformedObjectNameException", monEx);
+ }
+ }
+
+ public static InterfaceStatusMonitor getInstance() {
+ return interfaceStatusMonitor;
+ }
+
+ @Override
+ public String acquireServiceStatus() {
+ return serviceStatus;
+ }
+
+ public void reportStatus (String serviceStatus) {
+ this.serviceStatus = serviceStatus;
+ }
+}
--- /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.statusanddiag;
+
+public interface InterfaceStatusMonitorMBean {
+
+ public String acquireServiceStatus();
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.interfacemgr.impl.rev150325;
+
+import org.opendaylight.vpnservice.interfacemgr.InterfacemgrProvider;
+
+public class InterfacemgrImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.interfacemgr.impl.rev150325.AbstractInterfacemgrImplModule {
+ public InterfacemgrImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public InterfacemgrImplModule(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.interfacemgr.impl.rev150325.InterfacemgrImplModule 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() {
+ InterfacemgrProvider provider = new InterfacemgrProvider();
+ provider.setRpcProviderRegistry(getRpcRegistryDependency());
+ provider.setNotificationService(getNotificationServiceDependency());
+ provider.setMdsalManager(getMdsalutilDependency());
+ getBrokerDependency().registerProvider(provider);
+ return provider;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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
+ */
+/*
+* Generated file
+*
+* Generated from: yang module name: interfacemgr-impl yang module local name: interfacemgr-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Mon Mar 30 16:35:19 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.interfacemgr.impl.rev150325;
+public class InterfacemgrImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.interfacemgr.impl.rev150325.AbstractInterfacemgrImplModuleFactory {
+
+}
--- /dev/null
+module interfacemgr-impl {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:interfacemgr:impl";
+ prefix "interfacemgr-impl";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import opendaylight-sal-binding-broker-impl { prefix md-sal-binding-impl; revision-date 2013-10-28;}
+ import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
+ import odl-interface {prefix odlif; revision-date 2015-03-31;}
+ import odl-mdsalutil { prefix odl-mdsal; revision-date 2015-04-10;}
+
+ description
+ "Service definition for interfacemgr project";
+
+ revision "2015-03-25" {
+ description
+ "Initial revision";
+ }
+
+ identity interfacemgr-impl {
+ base config:module-type;
+ config:provided-service odlif:odl-interface;
+ config:java-name-prefix InterfacemgrImpl;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case interfacemgr-impl {
+ when "/config:modules/config:module/config:type = 'interfacemgr-impl'";
+ container broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-broker-osgi-registry;
+ }
+ }
+ }
+ container mdsalutil {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity odl-mdsal:odl-mdsalutil;
+ }
+ }
+ }
+ container rpc-registry {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-rpc-registry;
+ }
+ }
+ }
+ container notification-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding-impl:binding-new-notification-service;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+package org.opendaylight.vpnservice.interfacemgr.test;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+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.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.confighelpers.FlowBasedServicesConfigBindHelper;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.confighelpers.FlowBasedServicesConfigUnbindHelper;
+import org.opendaylight.vpnservice.mdsalutil.*;
+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.ietf.interfaces.rev140508.interfaces.Interface;
+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.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
+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.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+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.StypeOpenflow;
+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.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.BoundServicesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class FlowBasedServicesConfigurationTest {
+
+ BigInteger dpId = BigInteger.valueOf(1);
+ int flowPriority = 0;
+ int instructionKeyval = 2;
+ long portNum = 2;
+ Interface interfaceEnabled = null;
+ String serviceName = "VPN";
+ InstanceIdentifier<BoundServices> boundServicesIid = null;
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface stateInterface;
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceStateIdentifier = null;
+ BoundServices boundServiceNew = null;
+ NodeConnectorId nodeConnectorId = null;
+ ServicesInfo servicesInfo = null;
+ ServicesInfo servicesInfoUnbind = null;
+ StypeOpenflow stypeOpenflow = null;
+ InstanceIdentifier<Interface> interfaceInstanceIdentifier = null;
+ InstanceIdentifier<Flow> flowInstanceId = null;
+ Flow ingressFlow = null;
+ Instruction instruction = null;
+ InstructionKey instructionKey = null;
+ List<Instruction>instructions = new ArrayList<>();
+ short key = 0;
+ int ifIndexval = 100;
+
+ @Mock DataBroker dataBroker;
+ @Mock ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
+ @Mock ReadOnlyTransaction mockReadTx;
+ @Mock WriteTransaction mockWriteTx;
+
+ FlowBasedServicesConfigBindHelper bindHelper;
+ FlowBasedServicesConfigUnbindHelper unbindHelper;
+
+ @Before
+ public void setUp() throws Exception {
+ when(dataBroker.registerDataChangeListener(
+ any(LogicalDatastoreType.class),
+ any(InstanceIdentifier.class),
+ any(DataChangeListener.class),
+ any(DataChangeScope.class)))
+ .thenReturn(dataChangeListenerRegistration);
+ setupMocks();
+ }
+
+ private void setupMocks(){
+
+ interfaceEnabled = InterfaceManagerTestUtil.buildInterface(InterfaceManagerTestUtil.interfaceName, "Test Vlan Interface1",true,L2vlan.class,dpId);
+ nodeConnectorId = InterfaceManagerTestUtil.buildNodeConnectorId(dpId, portNum);
+ interfaceInstanceIdentifier = IfmUtil.buildId(InterfaceManagerTestUtil.interfaceName);
+
+ InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
+ List<String> lowerLayerIfList = new ArrayList<>();
+ lowerLayerIfList.add(nodeConnectorId.getValue());
+ ifaceBuilder.setOperStatus(OperStatus.Up).setAdminStatus(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus.Up)
+ .setPhysAddress(PhysAddress.getDefaultInstance("AA:AA:AA:AA:AA:AA"))
+ .setIfIndex(ifIndexval)
+ .setLowerLayerIf(lowerLayerIfList)
+ .setKey(IfmUtil.getStateInterfaceKeyFromName(InterfaceManagerTestUtil.interfaceName))
+ .setName(InterfaceManagerTestUtil.interfaceName);
+
+ stypeOpenflow = InterfaceManagerTestUtil.buildStypeOpenflow(dpId, flowPriority,NwConstants.LPORT_DISPATCHER_TABLE,instructions);
+ boundServiceNew = InterfaceManagerTestUtil.buildBoundServices(serviceName, key, new BoundServicesKey(key), stypeOpenflow);
+ instructionKey = new InstructionKey(instructionKeyval);
+ BigInteger[] metadataValues = IfmUtil.mergeOpenflowMetadataWriteInstructions(instructions);
+ short sIndex = boundServiceNew.getServicePriority();
+ BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(ifaceBuilder.getIfIndex(),
+ ++sIndex, metadataValues[0]);
+ BigInteger mask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(
+ MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
+ MetaDataUtil.METADATA_MASK_LPORT_TAG, metadataValues[1]);
+
+ instruction = InterfaceManagerTestUtil.buildInstruction(InterfaceManagerTestUtil.buildWriteMetaDataCase(InterfaceManagerTestUtil.buildWriteMetaData(metadata, mask)),
+ new InstructionKey(instructionKey));
+ instructions.add(instruction);
+ ServicesInfoKey servicesInfoKey = new ServicesInfoKey(InterfaceManagerTestUtil.interfaceName);
+ boundServicesIid = InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class, servicesInfoKey).
+ child(BoundServices.class, new BoundServicesKey(key)).build();
+
+ interfaceStateIdentifier = IfmUtil.buildStateInterfaceId(interfaceEnabled.getName());
+ stateInterface = ifaceBuilder.build();
+ List<BoundServices> boundServiceslist = new ArrayList<>();
+ boundServiceslist.add(boundServiceNew);
+ servicesInfo = InterfaceManagerTestUtil.buildServicesInfo(InterfaceManagerTestUtil.interfaceName, servicesInfoKey, boundServiceslist);
+ servicesInfoUnbind = InterfaceManagerTestUtil.buildServicesInfo(InterfaceManagerTestUtil.interfaceName,servicesInfoKey,new ArrayList<>());
+
+ String flowRef = InterfaceManagerTestUtil.buildflowRef(dpId,InterfaceManagerTestUtil.interfaceName,boundServiceNew.getServiceName(),boundServiceNew.getServicePriority());
+ List<Instruction> instructionList = boundServiceNew.getAugmentation(StypeOpenflow.class).getInstruction();
+ String serviceRef = boundServiceNew.getServiceName();
+ List<MatchInfo> matches = new ArrayList<>();
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ MetaDataUtil.getMetaDataForLPortDispatcher(ifaceBuilder.getIfIndex(), boundServiceNew.getServicePriority()),
+ MetaDataUtil.getMetaDataMaskForLPortDispatcher() }));
+ ingressFlow = MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef, boundServiceNew.getServicePriority(), serviceRef, 0, 0,
+ stypeOpenflow.getFlowCookie(), matches, instructionList);
+ FlowKey flowKey = new FlowKey(new FlowId(ingressFlow.getId()));
+ flowInstanceId = InterfaceManagerTestUtil.getFlowInstanceIdentifier(dpId,ingressFlow.getTableId(),flowKey);
+
+ when(dataBroker.newReadOnlyTransaction()).thenReturn(mockReadTx);
+ when(dataBroker.newWriteOnlyTransaction()).thenReturn(mockWriteTx);
+ }
+
+ @Test
+ public void testConfigBindSingleService(){
+
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> expectedStateInterface = Optional.of(stateInterface);
+ Optional<Interface> expectedInterface = Optional.of(interfaceEnabled);
+ Optional<ServicesInfo>expectedservicesInfo = Optional.of(servicesInfo);
+
+ ServicesInfoKey servicesInfoKey = new ServicesInfoKey(InterfaceManagerTestUtil.interfaceName);
+ InstanceIdentifier.InstanceIdentifierBuilder<ServicesInfo> servicesInfoIdentifierBuilder =
+ InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class, servicesInfoKey);
+
+
+ doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL,interfaceStateIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedservicesInfo)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, servicesInfoIdentifierBuilder.build());
+
+ bindHelper.bindService(boundServicesIid,boundServiceNew,dataBroker);
+
+ verify(mockWriteTx).put(LogicalDatastoreType.CONFIGURATION,flowInstanceId,ingressFlow, true);
+ }
+
+ @Test
+ public void testConfigUnbindSingleService(){
+
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> expectedStateInterface = Optional.of(stateInterface);
+ Optional<Interface> expectedInterface = Optional.of(interfaceEnabled);
+ Optional<ServicesInfo>expectedservicesInfo = Optional.of(servicesInfoUnbind);
+
+ ServicesInfoKey servicesInfoKey = new ServicesInfoKey(InterfaceManagerTestUtil.interfaceName);
+ InstanceIdentifier.InstanceIdentifierBuilder<ServicesInfo> servicesInfoIdentifierBuilder =
+ InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class, servicesInfoKey);
+
+ doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL,interfaceStateIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedservicesInfo)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION,servicesInfoIdentifierBuilder.build());
+
+ unbindHelper.unbindService(boundServicesIid,boundServiceNew,dataBroker);
+
+ verify(mockWriteTx).delete(LogicalDatastoreType.CONFIGURATION,flowInstanceId);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.vpnservice.interfacemgr.test;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+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.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.statehelpers.FlowBasedServicesStateBindHelper;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.statehelpers.FlowBasedServicesStateUnbindHelper;
+import org.opendaylight.vpnservice.mdsalutil.*;
+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.ietf.interfaces.rev140508.InterfaceType;
+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.state.Interface.OperStatus;
+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.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+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.StypeOpenflow;
+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.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.BoundServicesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class FlowBasedServicesStateConfigurationTest {
+
+ Interface interfaceEnabled = null;
+ long portNum = 2;
+ int instructionKeyval = 2;
+ InstanceIdentifier<Interface> interfaceInstanceIdentifier = null;
+ InstanceIdentifier<Flow> flowInstanceId = null;
+ Flow ingressFlow = null;
+ BigInteger dpId = BigInteger.valueOf(1);
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface stateInterface;
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceStateIdentifier = null;
+ ServicesInfo servicesInfo = null;
+ NodeConnectorId nodeConnectorId = null;
+ BoundServices boundService = null;
+ StypeOpenflow stypeOpenflow = null;
+ Instruction instruction = null;
+ InstructionKey instructionKey = null;
+ List<Instruction>instructions = new ArrayList<>();
+ short key =0;
+ int ifIndexval = 100;
+ int flowpriority = 2;
+ String serviceName = "VPN";
+
+ @Mock DataBroker dataBroker;
+ @Mock ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
+ @Mock ReadOnlyTransaction mockReadTx;
+ @Mock WriteTransaction mockWriteTx;
+
+ FlowBasedServicesStateBindHelper bindHelper;
+ FlowBasedServicesStateUnbindHelper unbindHelper;
+
+ @Before
+ public void setUp() throws Exception {
+ when(dataBroker.registerDataChangeListener(
+ any(LogicalDatastoreType.class),
+ any(InstanceIdentifier.class),
+ any(DataChangeListener.class),
+ any(DataChangeScope.class)))
+ .thenReturn(dataChangeListenerRegistration);
+ setupMocks();
+ }
+
+ private void setupMocks(){
+
+ interfaceEnabled = InterfaceManagerTestUtil.buildInterface(InterfaceManagerTestUtil.interfaceName, "Test Vlan Interface1", true, L2vlan.class, dpId);
+ interfaceInstanceIdentifier = IfmUtil.buildId(InterfaceManagerTestUtil.interfaceName);
+ nodeConnectorId = InterfaceManagerTestUtil.buildNodeConnectorId(BigInteger.valueOf(1), portNum);
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder ifaceBuilder = new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder();
+ List<String> lowerLayerIfList = new ArrayList<>();
+ lowerLayerIfList.add(nodeConnectorId.getValue());
+ ifaceBuilder.setOperStatus(OperStatus.Up).setAdminStatus(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus.Up)
+ .setPhysAddress(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress.getDefaultInstance("AA:AA:AA:AA:AA:AA"))
+ .setIfIndex(ifIndexval)
+ .setLowerLayerIf(lowerLayerIfList)
+ .setKey(IfmUtil.getStateInterfaceKeyFromName(InterfaceManagerTestUtil.interfaceName))
+ .setName(InterfaceManagerTestUtil.interfaceName).setType(interfaceEnabled.getType());
+ stypeOpenflow = InterfaceManagerTestUtil.buildStypeOpenflow(dpId,flowpriority, NwConstants.LPORT_DISPATCHER_TABLE, instructions);
+ instructionKey = new InstructionKey(instructionKeyval);
+ BigInteger[] metadataValues = IfmUtil.mergeOpenflowMetadataWriteInstructions(instructions);
+ boundService = InterfaceManagerTestUtil.buildBoundServices(serviceName,key,new BoundServicesKey(key),stypeOpenflow);
+ short sIndex = boundService.getServicePriority();
+ BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(ifaceBuilder.getIfIndex(),
+ ++sIndex, metadataValues[0]);
+ BigInteger mask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(
+ MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
+ MetaDataUtil.METADATA_MASK_LPORT_TAG, metadataValues[1]);
+ instruction = InterfaceManagerTestUtil.buildInstruction(InterfaceManagerTestUtil.buildWriteMetaDataCase(InterfaceManagerTestUtil.buildWriteMetaData(metadata, mask)),
+ new InstructionKey(instructionKey));
+ instructions.add(instruction);
+ stateInterface = ifaceBuilder.build();
+ ServicesInfoKey servicesInfoKey = new ServicesInfoKey(InterfaceManagerTestUtil.interfaceName);
+ List<BoundServices> lowerlayerIfList = new ArrayList<>();
+ lowerlayerIfList.add(boundService);
+ interfaceStateIdentifier = IfmUtil.buildStateInterfaceId(interfaceEnabled.getName());
+ servicesInfo = InterfaceManagerTestUtil.buildServicesInfo(InterfaceManagerTestUtil.interfaceName,servicesInfoKey,lowerlayerIfList);
+
+ String flowRef = InterfaceManagerTestUtil.buildflowRef(dpId, InterfaceManagerTestUtil.interfaceName, boundService.getServiceName(), boundService.getServicePriority());
+ List<Instruction> instructionList = boundService.getAugmentation(StypeOpenflow.class).getInstruction();
+ String serviceRef = boundService.getServiceName();
+ List<MatchInfo> matches = new ArrayList<>();
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ MetaDataUtil.getMetaDataForLPortDispatcher(ifaceBuilder.getIfIndex(), boundService.getServicePriority()),
+ MetaDataUtil.getMetaDataMaskForLPortDispatcher() }));
+ ingressFlow = MDSALUtil.buildFlowNew(stypeOpenflow.getDispatcherTableId(), flowRef, boundService.getServicePriority(), serviceRef, 0, 0,
+ stypeOpenflow.getFlowCookie(), matches, instructionList);
+ FlowKey flowKey = new FlowKey(new FlowId(ingressFlow.getId()));
+ flowInstanceId = InterfaceManagerTestUtil.getFlowInstanceIdentifier(dpId,ingressFlow.getTableId(),flowKey);
+
+ when(dataBroker.newReadOnlyTransaction()).thenReturn(mockReadTx);
+ when(dataBroker.newWriteOnlyTransaction()).thenReturn(mockWriteTx);
+ }
+
+ @Test
+ public void testStateBindSingleService(){
+
+ Optional<ServicesInfo>expectedservicesInfo = Optional.of(servicesInfo);
+ Optional<Interface> expectedInterface = Optional.of(interfaceEnabled);
+ Optional<NodeConnectorId>expectednodeconnectorId = Optional.of(nodeConnectorId);
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> expectedStateInterface = Optional.of(stateInterface);
+
+ ServicesInfoKey servicesInfoKey = new ServicesInfoKey(InterfaceManagerTestUtil.interfaceName);
+ InstanceIdentifier.InstanceIdentifierBuilder<ServicesInfo> servicesInfoIdentifierBuilder =
+ InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class, servicesInfoKey);
+
+ doReturn(Futures.immediateCheckedFuture(expectedservicesInfo)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION,servicesInfoIdentifierBuilder.build());
+ doReturn(Futures.immediateCheckedFuture(expectedInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectednodeconnectorId)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL,interfaceStateIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL,interfaceStateIdentifier);
+
+ bindHelper.bindServicesOnInterface(stateInterface,dataBroker);
+
+ verify(mockWriteTx).put(LogicalDatastoreType.CONFIGURATION,flowInstanceId,ingressFlow, true);
+
+ }
+
+ @Test
+ public void testStateUnbindSingleService(){
+
+ Optional<ServicesInfo>expectedservicesInfo = Optional.of(servicesInfo);
+ Optional<Interface> expectedInterface = Optional.of(interfaceEnabled);
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> expectedStateInterface = Optional.of(stateInterface);
+
+ ServicesInfoKey servicesInfoKey = new ServicesInfoKey(InterfaceManagerTestUtil.interfaceName);
+ InstanceIdentifier.InstanceIdentifierBuilder<ServicesInfo> servicesInfoIdentifierBuilder =
+ InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class, servicesInfoKey);
+
+ doReturn(Futures.immediateCheckedFuture(expectedservicesInfo)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION,servicesInfoIdentifierBuilder.build());
+ doReturn(Futures.immediateCheckedFuture(expectedInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL,interfaceStateIdentifier);
+
+ unbindHelper.unbindServicesFromInterface(stateInterface,dataBroker);
+
+ verify(mockWriteTx).delete(LogicalDatastoreType.CONFIGURATION,flowInstanceId);
+ }
+}
--- /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.test;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+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.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.confighelpers.HwVTEPConfigRemoveHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.confighelpers.HwVTEPInterfaceConfigAddHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.statehelpers.HwVTEPInterfaceStateRemoveHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.statehelpers.HwVTEPInterfaceStateUpdateHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.utilities.SouthboundUtils;
+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.state.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeVxlanOverIpv4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.Tunnels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.tunnel.attributes.BfdParams;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.tunnel.attributes.BfdStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.tunnel.attributes.BfdStatusBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.TunnelInstanceInterfaceMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.tunnel.instance._interface.map.TunnelInstanceInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.tunnel.instance._interface.map.TunnelInstanceInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.tunnel.instance._interface.map.TunnelInstanceInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class HwVTEPConfigurationTest {
+
+ @Mock DataBroker dataBroker;
+ @Mock ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
+ @Mock ReadOnlyTransaction mockReadTx;
+ @Mock WriteTransaction mockWriteTx;
+ @Mock InstanceIdentifier<TunnelInstanceInterface> tunnelInterfaceId;
+ @Mock TunnelInstanceInterface tunnelInterface;
+ @Mock Tunnels newTunnel;
+ @Mock Tunnels oldTunnel;
+ HwVTEPInterfaceConfigAddHelper addHelper;
+ HwVTEPConfigRemoveHelper removeHelper;
+ HwVTEPInterfaceStateUpdateHelper updateHelper;
+ HwVTEPInterfaceStateRemoveHelper stateRemoveHelper;
+
+ BigInteger dpId = BigInteger.valueOf(1);
+ Interface hwVTEPInterfaceEnabled;
+ Interface hwVTEPInterfaceDisabled;
+ ParentRefs parentRefs;
+ IfTunnel ifTunnel;
+ InstanceIdentifier<TerminationPoint> tpPath;
+ TerminationPoint terminationPoint;
+ InstanceIdentifier<Node> physicalSwitchId;
+ InstanceIdentifier<Node> globalId;
+ InstanceIdentifier<Tunnels> tunnelsInstanceIdentifier;
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceStateIdentifier;
+
+ @Before
+ public void setUp() throws Exception {
+ when(dataBroker.registerDataChangeListener(
+ any(LogicalDatastoreType.class),
+ any(InstanceIdentifier.class),
+ any(DataChangeListener.class),
+ any(DataChangeScope.class)))
+ .thenReturn(dataChangeListenerRegistration);
+ setupMocks();
+ }
+
+ @After
+ public void cleanUp(){
+ }
+
+ private void setupMocks() {
+ hwVTEPInterfaceEnabled = InterfaceManagerTestUtil.buildTunnelInterface(dpId, InterfaceManagerTestUtil.tunnelInterfaceName ,"Test hwVTEP Interface1", true, TunnelTypeVxlan.class, "192.168.56.101", "192.168.56.102");
+ hwVTEPInterfaceDisabled = InterfaceManagerTestUtil.buildTunnelInterface(dpId, InterfaceManagerTestUtil.tunnelInterfaceName ,"Test hwVTEP Interface1", false, TunnelTypeVxlan.class, "192.168.56.101", "192.168.56.102");
+ interfaceStateIdentifier = IfmUtil.buildStateInterfaceId(hwVTEPInterfaceEnabled.getName());
+ parentRefs = hwVTEPInterfaceEnabled.getAugmentation(ParentRefs.class);
+ ifTunnel = hwVTEPInterfaceEnabled.getAugmentation(IfTunnel.class);
+ physicalSwitchId = SouthboundUtils.createPhysicalSwitchInstanceIdentifier("s1");
+ globalId = SouthboundUtils.createPhysicalSwitchInstanceIdentifier("s1");
+ tunnelsInstanceIdentifier = org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.utilities.SouthboundUtils.
+ createTunnelsInstanceIdentifier(physicalSwitchId,
+ ifTunnel.getTunnelSource(), ifTunnel.getTunnelDestination());
+ tunnelInterfaceId = InstanceIdentifier.builder(TunnelInstanceInterfaceMap.class).
+ child(TunnelInstanceInterface.class, new TunnelInstanceInterfaceKey(tunnelsInstanceIdentifier.toString())).build();
+ tunnelInterface = new TunnelInstanceInterfaceBuilder().
+ setTunnelInstanceIdentifier(tunnelsInstanceIdentifier.toString()).setKey(new TunnelInstanceInterfaceKey(tunnelsInstanceIdentifier.toString())).setInterfaceName(hwVTEPInterfaceEnabled.getName()).build();
+
+ //Setup termination points
+ TerminationPointKey tpKey = SouthboundUtils.getTerminationPointKey(ifTunnel.getTunnelDestination().getIpv4Address().getValue());
+ tpPath = SouthboundUtils.createInstanceIdentifier(globalId, tpKey);
+ TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
+ HwvtepPhysicalLocatorAugmentationBuilder tpAugmentationBuilder =
+ new HwvtepPhysicalLocatorAugmentationBuilder();
+ tpBuilder.setKey(tpKey);
+ tpBuilder.setTpId(tpKey.getTpId());
+ tpAugmentationBuilder.setEncapsulationType(EncapsulationTypeVxlanOverIpv4.class);
+ SouthboundUtils.setDstIp(tpAugmentationBuilder, ifTunnel.getTunnelDestination());
+ tpBuilder.addAugmentation(HwvtepPhysicalLocatorAugmentation.class, tpAugmentationBuilder.build());
+ terminationPoint = tpBuilder.build();
+ // Setup mocks
+ when(dataBroker.newReadOnlyTransaction()).thenReturn(mockReadTx);
+ when(dataBroker.newWriteOnlyTransaction()).thenReturn(mockWriteTx);
+ }
+
+ @Test
+ public void testAddHwVTEPInterfaceWithGlobalNodeId() {
+ addHelper.addConfiguration(dataBroker, physicalSwitchId, globalId,
+ hwVTEPInterfaceEnabled, ifTunnel);
+
+ //Verify
+ verify(mockWriteTx).put(LogicalDatastoreType.CONFIGURATION, tpPath, terminationPoint, true);
+ verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, tunnelInterfaceId, tunnelInterface, true);
+ }
+
+ @Test
+ public void testAddHwVTEPInterfaceWithoutGlobalNodeId() {
+
+ addHelper.addConfiguration(dataBroker, physicalSwitchId ,null ,
+ hwVTEPInterfaceEnabled, ifTunnel);
+
+ //Verification already performed in testAddHwVTEPInterfaceWithGlobalNodeId()
+ }
+
+ @Test
+ public void testAddHwVTEPInterfaceWhenAdminStateDisabled() {
+
+ addHelper.addConfiguration(dataBroker, physicalSwitchId, globalId,
+ hwVTEPInterfaceDisabled, ifTunnel);
+
+ //Verification already performed in testAddHwVTEPInterfaceWithGlobalNodeId()
+ }
+ @Test
+ public void testDeleteHWVTEPInterface() {
+ removeHelper.removeConfiguration(dataBroker, hwVTEPInterfaceEnabled, physicalSwitchId, globalId);
+ //verification
+ verify(mockWriteTx).delete(LogicalDatastoreType.CONFIGURATION, tpPath);
+ verify(mockWriteTx).delete(LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
+ verify(mockWriteTx).delete(LogicalDatastoreType.OPERATIONAL, tunnelsInstanceIdentifier);
+ }
+
+ @Test
+ public void testUpdatePhysicalSwitch(){
+
+ Optional<TunnelInstanceInterface> tunnelInterfaceOptional = Optional.of(tunnelInterface);
+
+ doReturn(Futures.immediateCheckedFuture(tunnelInterfaceOptional)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, tunnelInterfaceId);
+ List<BfdStatus> bfdStatus = new ArrayList<BfdStatus>();
+ bfdStatus.add(new BfdStatusBuilder().setBfdStatusKey(SouthboundUtils.BFD_OP_STATE).setBfdStatusValue(SouthboundUtils.BFD_STATE_UP).build());
+ List bfdStatusSpy = spy(bfdStatus);
+ when(newTunnel.getBfdStatus()).thenReturn(bfdStatusSpy);
+ updateHelper.updatePhysicalSwitch(dataBroker, tunnelsInstanceIdentifier, newTunnel, oldTunnel);
+
+ //verify
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
+ IfmUtil.buildStateInterfaceId(hwVTEPInterfaceEnabled.getName());
+ InterfaceBuilder ifaceBuilder = new InterfaceBuilder().setOperStatus(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Up);
+ ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(hwVTEPInterfaceEnabled.getName()));
+ verify(mockWriteTx).merge(LogicalDatastoreType.OPERATIONAL, ifStateId, ifaceBuilder.build());
+ }
+
+ @Test
+ public void testStartBFDMonitoring(){
+
+ updateHelper.startBfdMonitoring(dataBroker, tunnelsInstanceIdentifier, newTunnel);
+
+ TunnelsBuilder tBuilder = new TunnelsBuilder();
+ tBuilder.setKey(new TunnelsKey(newTunnel.getLocalLocatorRef(), newTunnel.getRemoteLocatorRef()));
+ tBuilder.setLocalLocatorRef(newTunnel.getLocalLocatorRef());
+ tBuilder.setRemoteLocatorRef(newTunnel.getLocalLocatorRef());
+ List <BfdParams> bfdParams = new ArrayList<>();
+ SouthboundUtils.fillBfdParameters(bfdParams, null);
+ tBuilder.setBfdParams(bfdParams);
+ //Verify
+ verify(mockWriteTx).put(LogicalDatastoreType.CONFIGURATION, tunnelsInstanceIdentifier, tBuilder.build(), true);
+ }
+
+ @Test
+ public void testRemoveExternalTunnels(){
+
+ stateRemoveHelper.removeExternalTunnel(dataBroker, tunnelsInstanceIdentifier);
+
+ //Verify
+ verify(mockWriteTx).delete(LogicalDatastoreType.CONFIGURATION, tunnelsInstanceIdentifier);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
+
+import java.math.BigInteger;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+
+public class IfmUtilTest {
+
+ @Mock NodeConnectorId ncId;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void testDpnConversions() {
+ String NodeId = IfmUtil.buildDpnNodeId(BigInteger.valueOf(101)).getValue();
+ assertEquals("openflow:101", NodeId);
+ when(ncId.getValue()).thenReturn("openflow:101:11");
+ assertEquals("101",IfmUtil.getDpnFromNodeConnectorId(ncId));
+ }
+
+}
--- /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.test;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Maps;
+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.interfacemgr.IfmConstants;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.utilities.SouthboundUtils;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+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.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+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.interfaces.rev140508.InterfaceType;
+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.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
+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.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder;
+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.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.State;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.StateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+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.instruction.WriteMetadataCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadata;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+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.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+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.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsKey;
+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.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.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 org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools;
+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.meta.rev151007._if.indexes._interface.map.IfIndexInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._if.indexes._interface.map.IfIndexInterfaceBuilder;
+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.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.*;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev130712.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+
+import java.math.BigInteger;
+import java.util.*;
+
+public class InterfaceManagerTestUtil {
+ public static final String interfaceName = "s1-eth1";
+ public static final String childInterface = "s1-eth1-trunk";
+ public static final String tunnelInterfaceName = "s2-gre1";
+ public static final TopologyId OVSDB_TOPOLOGY_ID = new TopologyId(new Uri("ovsdb:1"));
+
+ public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface buildStateInterface(String ifaceName, String physAddress,
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus opState){
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder ifaceBuilder = new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder();
+ if(physAddress != null) {
+ ifaceBuilder.setPhysAddress(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress.getDefaultInstance(physAddress));
+ }
+ ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(ifaceName));
+ ifaceBuilder.setOperStatus(opState);
+ return ifaceBuilder.build();
+ }
+
+ public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface buildStateInterface(
+ String ifName, NodeConnectorId ncId) {
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder ifaceBuilder =
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder();
+ ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(ifName));
+ ifaceBuilder.setOperStatus(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Up);
+ ifaceBuilder.setLowerLayerIf(Arrays.asList(ncId.getValue()));
+ return ifaceBuilder.build();
+ }
+
+ public static InstanceIdentifier<NodeConnector> getNcIdent(String nodeKey, NodeConnectorId ncId) {
+ return InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, new NodeKey(new NodeId(nodeKey)))
+ .child(NodeConnector.class, new NodeConnectorKey(ncId))
+ .build();
+ }
+
+ public static InstanceIdentifier<Flow> getFlowInstanceIdentifier(BigInteger dpId,short key,FlowKey flowKey){
+
+ org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node nodeDpn;
+ NodeId nodeId = new NodeId("openflow:" + dpId);
+ nodeDpn = InterfaceManagerTestUtil.buildNode(nodeId,new NodeKey(nodeId));
+ return InstanceIdentifier.builder(Nodes.class)
+ .child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,nodeDpn.getKey())
+ .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(key)).child(Flow.class, flowKey).build();
+ }
+
+ public static InstanceIdentifier<FlowCapableNodeConnector> getFlowCapableNodeConnectorIdentifier(String nodeKey, NodeConnectorId ncId) {
+ return InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, new NodeKey(new NodeId(nodeKey)))
+ .child(NodeConnector.class, new NodeConnectorKey(ncId)).augmentation(FlowCapableNodeConnector.class)
+ .build();
+ }
+
+ public static Interface buildInterface(String ifName, String desc, boolean enabled, Object ifType,
+ BigInteger dpn) {
+ InterfaceBuilder builder = new InterfaceBuilder().setKey(new InterfaceKey(ifName)).setName(ifName)
+ .setDescription(desc).setEnabled(enabled).setType((Class<? extends InterfaceType>) ifType);
+ ParentRefs parentRefs = new ParentRefsBuilder().setDatapathNodeIdentifier(dpn).setParentInterface(ifName).build();
+ builder.addAugmentation(ParentRefs.class, parentRefs);
+ if(ifType.equals(L2vlan.class)){
+ IfL2vlan l2vlan = new IfL2vlanBuilder().setVlanId(VlanId.getDefaultInstance("0"))
+ .setL2vlanMode(IfL2vlan.L2vlanMode.Trunk).build();
+ builder.addAugmentation(IfL2vlan.class, l2vlan);
+ }else if(ifType.equals(IfTunnel.class)){
+ IfTunnel tunnel = new IfTunnelBuilder().setTunnelDestination(null).setTunnelGateway(null).setTunnelSource(null)
+ .setTunnelInterfaceType(null).build();
+ builder.addAugmentation(IfTunnel.class, tunnel);
+ }
+ return builder.build();
+ }
+
+ public static Interface buildTunnelInterface(BigInteger dpn, String ifName, String desc, boolean enabled, Class<? extends TunnelTypeBase> tunType,
+ String remoteIpStr, String localIpStr) {
+ InterfaceBuilder builder = new InterfaceBuilder().setKey(new InterfaceKey(ifName)).setName(ifName)
+ .setDescription(desc).setEnabled(enabled).setType(Tunnel.class);
+ ParentRefs parentRefs = new ParentRefsBuilder().setDatapathNodeIdentifier(dpn).build();
+ builder.addAugmentation(ParentRefs.class, parentRefs);
+ IpAddress remoteIp = new IpAddress(Ipv4Address.getDefaultInstance(remoteIpStr));
+ IpAddress localIp = new IpAddress(Ipv4Address.getDefaultInstance(localIpStr));
+ IfTunnel tunnel = new IfTunnelBuilder().setTunnelDestination(remoteIp).setTunnelGateway(localIp).setTunnelSource(localIp)
+ .setTunnelInterfaceType( tunType).setInternal(true).setMonitorEnabled(false).build();
+ builder.addAugmentation(IfTunnel.class, tunnel);
+ return builder.build();
+ }
+ public static IfIndexInterface buildIfIndexInterface(int ifindex, String interfaceName) {
+ IfIndexInterfaceBuilder builder = new IfIndexInterfaceBuilder().setKey(new IfIndexInterfaceKey(ifindex)).setIfIndex(ifindex).setInterfaceName(interfaceName);
+ return builder.build();
+ }
+
+ public static StypeOpenflow buildStypeOpenflow(BigInteger dpId, int flowpriority, short dispatchertableId , List list){
+ StypeOpenflowBuilder builder = new StypeOpenflowBuilder().setFlowCookie(dpId).setDispatcherTableId(dispatchertableId)
+ .setFlowPriority(flowpriority).setInstruction(list);
+ return builder.build();
+ }
+
+ public static WriteMetadata buildWriteMetaData(BigInteger meta, BigInteger mask){
+ WriteMetadataBuilder builder = new WriteMetadataBuilder().setMetadata(meta).setMetadataMask(mask);
+ return builder.build();
+ }
+
+ public static WriteMetadataCase buildWriteMetaDataCase(WriteMetadata writeMetadata){
+ WriteMetadataCaseBuilder builder = new WriteMetadataCaseBuilder().setWriteMetadata(writeMetadata);
+ return builder.build();
+ }
+
+ public static Instruction buildInstruction(WriteMetadataCase writeMetadataCase, InstructionKey instructionKey){
+ InstructionBuilder builder = new InstructionBuilder().setInstruction(writeMetadataCase).setKey(instructionKey);
+ return builder.build();
+ }
+ public static ServicesInfo buildServicesInfo(String name,ServicesInfoKey servicesInfoKey, List list){
+ ServicesInfoBuilder builder = new ServicesInfoBuilder().setInterfaceName(name).setBoundServices(list).setKey(servicesInfoKey);
+ return builder.build();
+ }
+
+ public static BoundServices buildBoundServices(String servicename, short servicepriority, BoundServicesKey boundServicesKey, StypeOpenflow stypeOpenflow){
+ BoundServicesBuilder builder = new BoundServicesBuilder().setServiceName(servicename).setKey(boundServicesKey).setServicePriority(servicepriority)
+ .setServiceType(ServiceTypeFlowBased.class).addAugmentation(StypeOpenflow.class,stypeOpenflow);
+ return builder.build();
+ }
+
+ public static org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node buildNode(NodeId nodeId , NodeKey nodeKey){
+ org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node nodeDpn;
+ nodeDpn = new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder().setId(nodeId).setKey(nodeKey).build();
+ return nodeDpn;
+ }
+
+ public static String buildflowRef(BigInteger dpId,String servicaName,String boundServicename, short servicePriority)
+ {
+ String flowRef = new StringBuffer().append(dpId).append(NwConstants.VLAN_INTERFACE_INGRESS_TABLE).append(NwConstants.FLOWID_SEPARATOR).
+ append(servicaName).append(NwConstants.FLOWID_SEPARATOR).append(servicePriority).toString();
+ return flowRef;
+ }
+
+ public static NodeConnector buildNodeConnector(NodeConnectorId ncId) {
+ NodeConnectorBuilder ncBuilder = new NodeConnectorBuilder()
+ .setId(ncId)
+ .setKey(new NodeConnectorKey(ncId));
+ return ncBuilder.build();
+ }
+
+ public static NodeConnector buildFlowCapableNodeConnector(NodeConnectorId ncId) {
+ NodeConnectorBuilder ncBuilder = new NodeConnectorBuilder()
+ .setId(ncId)
+ .setKey(new NodeConnectorKey(ncId));
+ FlowCapableNodeConnectorBuilder flowCapableNodeConnectorBuilder = new FlowCapableNodeConnectorBuilder().setHardwareAddress(MacAddress.getDefaultInstance("AA:AA:AA:AA:AA:AA"));
+ ncBuilder.addAugmentation(FlowCapableNodeConnector.class,flowCapableNodeConnectorBuilder.build());
+ return ncBuilder.build();
+ }
+
+ public static FlowCapableNodeConnector buildFlowCapableNodeConnector(boolean isPortDown, boolean isLive, String macAddress) {
+ PortConfig portConfig = new PortConfig(false, false, false, isPortDown);
+ State state = new StateBuilder().setBlocked(true).setLinkDown(false).setLive(isLive).build();
+ FlowCapableNodeConnectorBuilder fcNodeConnector = new FlowCapableNodeConnectorBuilder().
+ setHardwareAddress(MacAddress.getDefaultInstance(macAddress)).setConfiguration(portConfig).setState(state);
+ return fcNodeConnector.build();
+ }
+
+ public static NodeConnectorId buildNodeConnectorId(BigInteger dpn, long portNo) {
+ return new NodeConnectorId(buildNodeConnectorString(dpn, portNo));
+ }
+
+ public static String buildNodeConnectorString(BigInteger dpn, long portNo){
+ return new StringBuffer().append(IfmConstants.OF_URI_PREFIX).
+ append(dpn).append(IfmConstants.OF_URI_SEPARATOR).
+ append(portNo).toString();
+ }
+
+ public static InstanceIdentifier<BridgeInterfaceEntry> buildBridgeEntryId(BigInteger dpn, String interfaceName){
+ BridgeEntryKey bridgeEntryKey = new BridgeEntryKey(dpn);
+ BridgeInterfaceEntryKey bridgeInterfaceEntryKey = new BridgeInterfaceEntryKey(interfaceName);
+ InstanceIdentifier<BridgeInterfaceEntry> bridgeInterfaceEntryIid =
+ InterfaceMetaUtils.getBridgeInterfaceEntryIdentifier(bridgeEntryKey, bridgeInterfaceEntryKey);
+ return bridgeInterfaceEntryIid;
+ }
+
+ public static BridgeEntry buildBridgeEntry(BigInteger dpn, BridgeInterfaceEntry bridgeInterfaceEntry){
+ BridgeEntryKey bridgeEntryKey = new BridgeEntryKey(dpn);
+ BridgeEntry bridgeEntry = new BridgeEntryBuilder().setKey(bridgeEntryKey).setDpid(dpn).
+ setBridgeInterfaceEntry(Arrays.asList(bridgeInterfaceEntry)).build();
+ return bridgeEntry;
+ }
+
+ public static BridgeInterfaceEntry buildBridgeInterfaceEntry(BigInteger dpn, String interfaceName){
+ BridgeEntryKey bridgeEntryKey = new BridgeEntryKey(dpn);
+ BridgeInterfaceEntryKey bridgeInterfaceEntryKey = new BridgeInterfaceEntryKey(interfaceName);
+ BridgeInterfaceEntryBuilder entryBuilder = new BridgeInterfaceEntryBuilder().setKey(bridgeInterfaceEntryKey)
+ .setInterfaceName(interfaceName);
+ return entryBuilder.build();
+ }
+
+ public static InstanceIdentifier<OvsdbBridgeAugmentation> getOvsdbAugmentationInstanceIdentifier(String portName,
+ org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node node) {
+ InstanceIdentifier<OvsdbBridgeAugmentation> ovsdbBridgeAugmentationInstanceIdentifier = InstanceIdentifier
+ .create(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(OVSDB_TOPOLOGY_ID))
+ .child(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node.class,node.getKey())
+ .augmentation(OvsdbBridgeAugmentation.class);
+ return ovsdbBridgeAugmentationInstanceIdentifier;
+ }
+
+ public static OvsdbBridgeAugmentation getOvsdbBridgeRef(String bridgeName){
+ OvsdbBridgeAugmentationBuilder builder = new OvsdbBridgeAugmentationBuilder().setBridgeName(new OvsdbBridgeName(bridgeName));
+ return builder.build();
+ }
+
+ public static InstanceIdentifier<TerminationPoint> getTerminationPointId(InstanceIdentifier<?> bridgeIid, String portName){
+ InstanceIdentifier<TerminationPoint> tpIid = SouthboundUtils.createTerminationPointInstanceIdentifier(
+ InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node.class)), portName);
+ return tpIid;
+ }
+
+ public static TerminationPoint getTerminationPoint(InstanceIdentifier<?> bridgeIid, OvsdbBridgeAugmentation bridgeNode,
+ String portName, int vlanId, Class type,
+ Interface iface) {
+ InstanceIdentifier<TerminationPoint> tpIid = SouthboundUtils.createTerminationPointInstanceIdentifier(
+ InstanceIdentifier.keyOf(bridgeIid.firstIdentifierOf(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node.class)), portName);
+ OvsdbTerminationPointAugmentationBuilder tpAugmentationBuilder = new OvsdbTerminationPointAugmentationBuilder();
+
+ tpAugmentationBuilder.setName(portName);
+
+ if (type != null) {
+ tpAugmentationBuilder.setInterfaceType(type);
+ }
+ IfTunnel ifTunnel = iface.getAugmentation(IfTunnel.class);
+ Map<String, String> options = Maps.newHashMap();
+ options.put("key", "flow");
+
+ IpAddress localIp = ifTunnel.getTunnelSource();
+ options.put("local_ip", localIp.getIpv4Address().getValue());
+
+ IpAddress remoteIp = ifTunnel.getTunnelDestination();
+ options.put("remote_ip", remoteIp.getIpv4Address().getValue());
+
+ if (options != null) {
+ List<Options> optionsList = new ArrayList<Options>();
+ for (Map.Entry<String, String> entry : options.entrySet()) {
+ OptionsBuilder optionsBuilder = new OptionsBuilder();
+ optionsBuilder.setKey(new OptionsKey(entry.getKey()));
+ optionsBuilder.setOption(entry.getKey());
+ optionsBuilder.setValue(entry.getValue());
+ optionsList.add(optionsBuilder.build());
+ }
+ tpAugmentationBuilder.setOptions(optionsList);
+ }
+
+ if (vlanId != 0) {
+ tpAugmentationBuilder.setVlanMode(OvsdbPortInterfaceAttributes.VlanMode.Access);
+ tpAugmentationBuilder.setVlanTag(new VlanId(vlanId));
+ }
+
+ TerminationPointBuilder tpBuilder = new TerminationPointBuilder();
+ tpBuilder.setKey(InstanceIdentifier.keyOf(tpIid));
+ tpBuilder.addAugmentation(OvsdbTerminationPointAugmentation.class, tpAugmentationBuilder.build());
+ return tpBuilder.build();
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.vpnservice.interfacemgr.test;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+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.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.statehelpers.OvsInterfaceStateAddHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.statehelpers.OvsInterfaceStateRemoveHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.statehelpers.OvsInterfaceStateUpdateHelper;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+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.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.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.State;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.StateBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.*;
+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.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+
+import static org.mockito.Mockito.*;
+
+
+
+@RunWith(MockitoJUnitRunner.class)
+public class StateInterfaceTest {
+ BigInteger dpId = BigInteger.valueOf(1);
+ NodeConnectorId nodeConnectorId = null;
+ NodeConnector nodeConnector = null;
+ FlowCapableNodeConnector fcNodeConnectorNew = null;
+ Interface vlanInterfaceEnabled = null;
+ Interface vlanInterfaceDisabled = null;
+ Interface tunnelInterfaceEnabled;
+ Interface childVlanInterfaceEnabled = null;
+ InterfaceParentEntryKey interfaceParentEntryKey = null;
+ InterfaceParentEntryKey higherLayerInterfaceParentEntryKey = null;
+ IfIndexInterface IfindexInterface = null;
+ InstanceIdentifier<Interface> interfaceInstanceIdentifier = null;
+ InstanceIdentifier<Interface> childInterfaceInstanceIdentifier= null;
+ InstanceIdentifier<InterfaceParentEntry> interfaceParentEntryInstanceIdentifier = null;
+ InstanceIdentifier<FlowCapableNodeConnector> fcNodeConnectorId = null;
+ InstanceIdentifier<IfIndexInterface> ifIndexId =null;
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceStateIdentifier = null;
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> childInterfaceStateIdentifier = null;
+ InstanceIdentifier<InterfaceParentEntry> interfaceParentEntryIdentifier = null;
+ InstanceIdentifier<InterfaceParentEntry> higherLevelInterfaceParentEntryIdentifier = null;
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface stateInterface;
+ InterfaceParentEntry interfaceParentEntry;
+ InterfaceParentEntry higherLayerInterfaceParentEntry;
+
+ @Mock DataBroker dataBroker;
+ @Mock IdManagerService idManager;
+ @Mock IMdsalApiManager mdsalManager;
+ @Mock ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
+ @Mock ReadOnlyTransaction mockReadTx;
+ @Mock WriteTransaction mockWriteTx;
+ @Mock AlivenessMonitorService alivenessMonitorService;
+
+ OvsInterfaceStateAddHelper addHelper;
+ OvsInterfaceStateRemoveHelper removeHelper;
+ OvsInterfaceStateUpdateHelper updateHelper;
+
+ @Before
+ public void setUp() throws Exception {
+ when(dataBroker.registerDataChangeListener(
+ any(LogicalDatastoreType.class),
+ any(InstanceIdentifier.class),
+ any(DataChangeListener.class),
+ any(DataChangeScope.class)))
+ .thenReturn(dataChangeListenerRegistration);
+ setupMocks();
+ }
+
+ private void setupMocks() {
+ nodeConnectorId = InterfaceManagerTestUtil.buildNodeConnectorId(BigInteger.valueOf(1), 2);
+ nodeConnector = InterfaceManagerTestUtil.buildFlowCapableNodeConnector(nodeConnectorId);
+ fcNodeConnectorNew = nodeConnector.getAugmentation(FlowCapableNodeConnector.class);
+ fcNodeConnectorId = InterfaceManagerTestUtil.getFlowCapableNodeConnectorIdentifier("openflow:1", nodeConnectorId);
+ IfindexInterface = InterfaceManagerTestUtil.buildIfIndexInterface(100, InterfaceManagerTestUtil.interfaceName);
+ ifIndexId = InstanceIdentifier.builder(IfIndexesInterfaceMap.class).child(IfIndexInterface.class, new IfIndexInterfaceKey(100)).build();
+ interfaceInstanceIdentifier = InterfaceManagerCommonUtils.getInterfaceIdentifier(new InterfaceKey(InterfaceManagerTestUtil.interfaceName));
+ childInterfaceInstanceIdentifier = InterfaceManagerCommonUtils.getInterfaceIdentifier(new InterfaceKey(InterfaceManagerTestUtil.childInterface));
+ interfaceStateIdentifier = IfmUtil.buildStateInterfaceId(InterfaceManagerTestUtil.interfaceName);
+ childInterfaceStateIdentifier = IfmUtil.buildStateInterfaceId(InterfaceManagerTestUtil.childInterface);
+ vlanInterfaceEnabled = InterfaceManagerTestUtil.buildInterface(InterfaceManagerTestUtil.interfaceName, "Test Vlan Interface1", true, L2vlan.class, BigInteger.valueOf(1));
+ vlanInterfaceDisabled = InterfaceManagerTestUtil.buildInterface(InterfaceManagerTestUtil.interfaceName, "Test Vlan Interface1", false, L2vlan.class, BigInteger.valueOf(1));
+ tunnelInterfaceEnabled = InterfaceManagerTestUtil.buildTunnelInterface(dpId, InterfaceManagerTestUtil.tunnelInterfaceName ,"Test Tunnel Interface", true, TunnelTypeGre.class, "192.168.56.101", "192.168.56.102");
+ childVlanInterfaceEnabled = InterfaceManagerTestUtil.buildInterface(InterfaceManagerTestUtil.childInterface, "Test Vlan Interface2", true, L2vlan.class, BigInteger.valueOf(1));
+ interfaceParentEntryKey = new InterfaceParentEntryKey(InterfaceManagerTestUtil.interfaceName);
+ interfaceParentEntryIdentifier = InterfaceMetaUtils.getInterfaceParentEntryIdentifier(interfaceParentEntryKey);
+ higherLayerInterfaceParentEntryKey = new InterfaceParentEntryKey(InterfaceManagerTestUtil.childInterface);
+ higherLevelInterfaceParentEntryIdentifier= InterfaceMetaUtils.getInterfaceParentEntryIdentifier(higherLayerInterfaceParentEntryKey);
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder ifaceBuilder = new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder();
+ List<String> lowerLayerIfList = new ArrayList<>();
+ lowerLayerIfList.add(nodeConnectorId.getValue());
+ ifaceBuilder.setOperStatus(OperStatus.Up).setAdminStatus(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.AdminStatus.Up)
+ .setPhysAddress(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress.getDefaultInstance("AA:AA:AA:AA:AA:AA"))
+ .setIfIndex(100)
+ .setLowerLayerIf(lowerLayerIfList).setType(L2vlan.class);
+ ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(InterfaceManagerTestUtil.interfaceName));
+
+ stateInterface = ifaceBuilder.build();
+
+ InterfaceParentEntryBuilder ifaceParentEntryBuilder = new InterfaceParentEntryBuilder();
+ List<InterfaceChildEntry> ifaceChildEntryList= new ArrayList<>();
+ ifaceChildEntryList.add(new InterfaceChildEntryBuilder().setChildInterface(InterfaceManagerTestUtil.childInterface).build());
+ interfaceParentEntry = ifaceParentEntryBuilder.setInterfaceChildEntry(ifaceChildEntryList).build();
+
+ InterfaceParentEntryBuilder higherLayerIfParentEntryBuilder = new InterfaceParentEntryBuilder();
+ List<InterfaceChildEntry> ifaceChildEntryListForHigherParent= new ArrayList<>();
+ higherLayerInterfaceParentEntry = higherLayerIfParentEntryBuilder.setInterfaceChildEntry(ifaceChildEntryListForHigherParent).build();
+
+ when(dataBroker.newReadOnlyTransaction()).thenReturn(mockReadTx);
+ when(dataBroker.newWriteOnlyTransaction()).thenReturn(mockWriteTx);
+ }
+
+ @Test
+ public void testAddStateInterface() {
+ Optional<Interface> expectedInterface = Optional.of(vlanInterfaceEnabled);
+ AllocateIdOutput expectedId = new AllocateIdOutputBuilder().setIdValue(Long.valueOf("100")).build();
+ AllocateIdOutput expectedId2 = new AllocateIdOutputBuilder().setIdValue(Long.valueOf("200")).build();
+ Optional<InterfaceParentEntry>expectedParentEntry = Optional.of(interfaceParentEntry);
+ Optional<InterfaceParentEntry> higherLayerParentOptional = Optional.of(higherLayerInterfaceParentEntry);
+ Optional<Interface> expectedChildInterface = Optional.of(childVlanInterfaceEnabled);
+
+ Future<RpcResult<AllocateIdOutput>> idOutputOptional = RpcResultBuilder.success(expectedId).buildFuture();
+ Future<RpcResult<AllocateIdOutput>> idOutputOptional2 = RpcResultBuilder.success(expectedId).buildFuture();
+
+ doReturn(Futures.immediateCheckedFuture(expectedInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedParentEntry)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceParentEntryIdentifier);
+ doReturn(Futures.immediateCheckedFuture(higherLayerParentOptional)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, higherLevelInterfaceParentEntryIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedChildInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, childInterfaceInstanceIdentifier);
+
+ AllocateIdInput getIdInput = new AllocateIdInputBuilder()
+ .setPoolName(IfmConstants.IFM_IDPOOL_NAME)
+ .setIdKey(InterfaceManagerTestUtil.interfaceName).build();
+ doReturn(idOutputOptional).when(idManager).allocateId(getIdInput);
+ AllocateIdInput getIdInput2 = new AllocateIdInputBuilder()
+ .setPoolName(IfmConstants.IFM_IDPOOL_NAME)
+ .setIdKey(InterfaceManagerTestUtil.childInterface).build();
+ doReturn(idOutputOptional2).when(idManager).allocateId(getIdInput2);
+
+ addHelper.addState(dataBroker, idManager, mdsalManager, alivenessMonitorService,
+ nodeConnectorId, InterfaceManagerTestUtil.interfaceName, fcNodeConnectorNew);
+
+ //Add some verifications
+ verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier,
+ stateInterface,true);
+ }
+
+ @Test
+ public void testAddStateTunnelInterface() {
+
+ Optional<Interface> expectedInterface = Optional.of(tunnelInterfaceEnabled);
+ AllocateIdOutput expectedId = new AllocateIdOutputBuilder().setIdValue(Long.valueOf("100")).build();
+
+ Future<RpcResult<AllocateIdOutput>> idOutputOptional = RpcResultBuilder.success(expectedId).buildFuture();
+
+ doReturn(Futures.immediateCheckedFuture(expectedInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier);
+
+ AllocateIdInput getIdInput = new AllocateIdInputBuilder()
+ .setPoolName(IfmConstants.IFM_IDPOOL_NAME)
+ .setIdKey(InterfaceManagerTestUtil.interfaceName).build();
+ doReturn(idOutputOptional).when(idManager).allocateId(getIdInput);
+
+ addHelper.addState(dataBroker, idManager, mdsalManager, alivenessMonitorService,
+ nodeConnectorId, InterfaceManagerTestUtil.interfaceName, fcNodeConnectorNew);
+ }
+
+ @Test
+ public void testDeleteStateInterface() {
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface>
+ expectedStateInterface = Optional.of(stateInterface);
+ Optional<IfIndexInterface> expectedIfindexInterface = Optional.of(IfindexInterface);
+ Optional<Interface> expectedInterface = Optional.of(vlanInterfaceEnabled);
+ Optional<InterfaceParentEntry>expectedParentEntry = Optional.of(interfaceParentEntry);
+ Optional<InterfaceParentEntry> higherLayerParentOptional = Optional.of(higherLayerInterfaceParentEntry);
+
+ doReturn(Futures.immediateCheckedFuture(expectedIfindexInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, ifIndexId);
+ doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, childInterfaceStateIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedParentEntry)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceParentEntryIdentifier);
+ doReturn(Futures.immediateCheckedFuture(higherLayerParentOptional)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, higherLevelInterfaceParentEntryIdentifier);
+
+ ReleaseIdInput getIdInput = new ReleaseIdInputBuilder()
+ .setPoolName(IfmConstants.IFM_IDPOOL_NAME)
+ .setIdKey(InterfaceManagerTestUtil.interfaceName).build();
+
+ doReturn(Futures.immediateFuture(RpcResultBuilder.<Void>success().build())).when(idManager).releaseId(getIdInput);
+
+ removeHelper.removeState(idManager, mdsalManager, alivenessMonitorService, fcNodeConnectorId, dataBroker, InterfaceManagerTestUtil.interfaceName, fcNodeConnectorNew);
+
+ verify(mockWriteTx).delete(LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
+
+ }
+
+ @Test
+ public void testDeleteStateTunnelInterface() {
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface>
+ expectedStateInterface = Optional.of(stateInterface);
+ Optional<Interface> expectedInterface = Optional.of(tunnelInterfaceEnabled);
+
+ doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier);
+
+ removeHelper.removeState(idManager, mdsalManager, alivenessMonitorService, fcNodeConnectorId, dataBroker, InterfaceManagerTestUtil.interfaceName, fcNodeConnectorNew);
+
+ }
+
+ @Test
+ public void testUpdateStateInterface(){
+
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface>
+ expectedStateInterface = Optional.of(stateInterface);
+ Optional<InterfaceParentEntry>expectedParentEntry = Optional.of(interfaceParentEntry);
+ Optional<Interface> expectedInterface = Optional.of(vlanInterfaceEnabled);
+ Optional<Interface> expectedChildInterface = Optional.of(childVlanInterfaceEnabled);
+ Optional<InterfaceParentEntry> higherLayerParentOptional = Optional.of(higherLayerInterfaceParentEntry);
+
+ doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, childInterfaceStateIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedParentEntry)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceParentEntryIdentifier);
+ doReturn(Futures.immediateCheckedFuture(higherLayerParentOptional)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, higherLevelInterfaceParentEntryIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedChildInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, childInterfaceInstanceIdentifier);
+
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface parentInterface = InterfaceManagerTestUtil.buildStateInterface(InterfaceManagerTestUtil.interfaceName, null, OperStatus.Down);
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface childInterface = InterfaceManagerTestUtil.buildStateInterface(InterfaceManagerTestUtil.childInterface, null, OperStatus.Down);
+
+ FlowCapableNodeConnector fcNodeConnectorOld = InterfaceManagerTestUtil.buildFlowCapableNodeConnector(false, true, "AA:AA:AA:AA:AA:AA");
+ FlowCapableNodeConnector fcNodeConnectorNew = InterfaceManagerTestUtil.buildFlowCapableNodeConnector(true, false, "AA:AA:AA:AA:AA:AA");
+
+ updateHelper.updateState(fcNodeConnectorId, alivenessMonitorService, dataBroker, InterfaceManagerTestUtil.interfaceName, fcNodeConnectorNew, fcNodeConnectorOld);
+
+ verify(mockWriteTx).merge(LogicalDatastoreType.OPERATIONAL,interfaceStateIdentifier,parentInterface);
+ verify(mockWriteTx).merge(LogicalDatastoreType.OPERATIONAL,childInterfaceStateIdentifier,childInterface);
+ }
+}
--- /dev/null
+/**
+ * Created by eranjsu on 28-Dec-15.
+ */
+package org.opendaylight.vpnservice.interfacemgr.test;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+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.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.renderer.hwvtep.utilities.SouthboundUtils;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.statehelpers.OvsInterfaceTopologyStateAddHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.statehelpers.OvsInterfaceTopologyStateRemoveHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.statehelpers.OvsInterfaceTopologyStateUpdateHelper;
+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.state.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfdStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfdStatusBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.Mockito.*;
+
+
+@RunWith(MockitoJUnitRunner.class)
+public class TopologyStateInterfaceTest {
+
+ BigInteger dpId = BigInteger.valueOf(1);
+ InstanceIdentifier<OvsdbBridgeAugmentation>bridgeIid = null;
+ InstanceIdentifier<BridgeEntry> bridgeEntryIid = null;
+ OvsdbBridgeAugmentation bridgeNew;
+ OvsdbBridgeAugmentation bridgeOld;
+ BridgeEntry bridgeEntry = null;
+ ParentRefs parentRefs = null;
+ InstanceIdentifier<Interface> interfaceInstanceIdentifier = null;
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceStateIdentifier = null;
+ Interface tunnelInterfaceEnabled = null;
+ BridgeInterfaceEntry bridgeInterfaceEntry;
+ BridgeInterfaceEntryKey bridgeInterfaceEntryKey;
+
+ @Mock DataBroker dataBroker;
+ @Mock ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
+ @Mock ReadOnlyTransaction mockReadTx;
+ @Mock WriteTransaction mockWriteTx;
+ @Mock OvsdbTerminationPointAugmentation newTerminationPoint;
+
+ OvsInterfaceTopologyStateAddHelper addHelper;
+ OvsInterfaceTopologyStateRemoveHelper removeHelper;
+ OvsInterfaceTopologyStateUpdateHelper updateHelper;
+
+ @Before
+ public void setUp() throws Exception {
+ when(dataBroker.registerDataChangeListener(
+ any(LogicalDatastoreType.class),
+ any(InstanceIdentifier.class),
+ any(DataChangeListener.class),
+ any(DataChangeScope.class)))
+ .thenReturn(dataChangeListenerRegistration);
+ setupMocks();
+ }
+
+ private void setupMocks()
+ {
+ Node node = new NodeBuilder().setKey(null).setNodeId(null).build();
+ tunnelInterfaceEnabled = InterfaceManagerTestUtil.buildTunnelInterface(dpId, InterfaceManagerTestUtil.tunnelInterfaceName, "Test Interface1", true, TunnelTypeGre.class
+ , "192.168.56.101", "192.168.56.102");
+ bridgeIid = InterfaceManagerTestUtil.getOvsdbAugmentationInstanceIdentifier(InterfaceManagerTestUtil.interfaceName, node);
+ bridgeNew = InterfaceManagerTestUtil.getOvsdbBridgeRef("s1");
+ bridgeOld = InterfaceManagerTestUtil.getOvsdbBridgeRef("s1");
+ bridgeEntryIid = InterfaceMetaUtils.getBridgeEntryIdentifier(new BridgeEntryKey(dpId));
+ interfaceInstanceIdentifier = IfmUtil.buildId(InterfaceManagerTestUtil.tunnelInterfaceName);
+ interfaceStateIdentifier = IfmUtil.buildStateInterfaceId(newTerminationPoint.getName());
+ bridgeInterfaceEntryKey = new BridgeInterfaceEntryKey(InterfaceManagerTestUtil.tunnelInterfaceName);
+ bridgeInterfaceEntry =
+ new BridgeInterfaceEntryBuilder().setKey(bridgeInterfaceEntryKey)
+ .setInterfaceName(tunnelInterfaceEnabled.getName()).build();
+ bridgeEntry = InterfaceManagerTestUtil.buildBridgeEntry(dpId, bridgeInterfaceEntry);
+
+ when(dataBroker.newReadOnlyTransaction()).thenReturn(mockReadTx);
+ when(dataBroker.newWriteOnlyTransaction()).thenReturn(mockWriteTx);
+ }
+
+ @Test
+ public void testAddTopologyStateInterface()
+ {
+ Optional<OvsdbBridgeAugmentation>expectedOvsdbBridgeAugmentation = Optional.of(bridgeNew);
+ Optional<BridgeEntry> expectedBridgeEntry = Optional.of(bridgeEntry);
+ Optional<Interface> expectedInterface = Optional.of(tunnelInterfaceEnabled);
+
+ doReturn(Futures.immediateCheckedFuture(expectedInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedBridgeEntry)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION,bridgeEntryIid);
+
+ OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentation = new OvsdbBridgeAugmentationBuilder(bridgeNew);
+ ovsdbBridgeAugmentation.setDatapathId(DatapathId.getDefaultInstance("00:00:00:00:00:00:00:01"));
+ ovsdbBridgeAugmentation.setBridgeName(OvsdbBridgeName.getDefaultInstance("a"));
+ bridgeNew = ovsdbBridgeAugmentation.build();
+
+ addHelper.addPortToBridge(bridgeIid,bridgeNew,dataBroker);
+
+ BigInteger ovsdbDpId = BigInteger.valueOf(1);
+ BridgeRefEntryKey bridgeRefEntryKey = new BridgeRefEntryKey(ovsdbDpId);
+ InstanceIdentifier<BridgeRefEntry> bridgeEntryId =
+ InterfaceMetaUtils.getBridgeRefEntryIdentifier(bridgeRefEntryKey);
+ BridgeRefEntryBuilder tunnelDpnBridgeEntryBuilder =
+ new BridgeRefEntryBuilder().setKey(bridgeRefEntryKey).setDpid(ovsdbDpId)
+ .setBridgeReference(new OvsdbBridgeRef(bridgeIid));
+
+ verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, bridgeEntryId, tunnelDpnBridgeEntryBuilder.build(), true);
+ }
+
+ @Test
+ public void testDeleteTopologyStateInterface()
+ {
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, bridgeIid);
+ OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentation = new OvsdbBridgeAugmentationBuilder(bridgeOld);
+ ovsdbBridgeAugmentation.setDatapathId(DatapathId.getDefaultInstance("00:00:00:00:00:00:00:01"));
+ ovsdbBridgeAugmentation.setBridgeName(OvsdbBridgeName.getDefaultInstance("b"));
+ bridgeOld = ovsdbBridgeAugmentation.build();
+
+ removeHelper.removePortFromBridge(bridgeIid,bridgeOld,dataBroker);
+
+ BigInteger ovsdbDpId = BigInteger.valueOf(1);
+ BridgeRefEntryKey bridgeRefEntryKey = new BridgeRefEntryKey(ovsdbDpId);
+ InstanceIdentifier<BridgeRefEntry> bridgeEntryId =
+ InterfaceMetaUtils.getBridgeRefEntryIdentifier(bridgeRefEntryKey);
+
+ verify(mockWriteTx).delete(LogicalDatastoreType.OPERATIONAL,bridgeEntryId);
+ }
+
+ @Test
+ public void testUpdateBridgeReferenceEntry()
+ {
+ Optional<OvsdbBridgeAugmentation>expectedOvsdbBridgeAugmentation = Optional.of(bridgeNew);
+ Optional<BridgeEntry> expectedBridgeEntry = Optional.of(bridgeEntry);
+ Optional<Interface> expectedInterface = Optional.of(tunnelInterfaceEnabled);
+
+ doReturn(Futures.immediateCheckedFuture(expectedInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedBridgeEntry)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION,bridgeEntryIid);
+ doReturn(Futures.immediateCheckedFuture(expectedOvsdbBridgeAugmentation)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, bridgeIid);
+
+ OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentation = new OvsdbBridgeAugmentationBuilder(bridgeNew);
+ ovsdbBridgeAugmentation.setDatapathId(DatapathId.getDefaultInstance("00:00:00:00:00:00:00:01"));
+ ovsdbBridgeAugmentation.setBridgeName(OvsdbBridgeName.getDefaultInstance("a"));
+ bridgeNew = ovsdbBridgeAugmentation.build();
+
+ updateHelper.updateBridgeRefEntry(bridgeIid, bridgeNew, bridgeOld, dataBroker);
+ }
+
+ @Test
+ public void testUpdateTunnelState(){
+
+ List<InterfaceBfdStatus> interfaceBfdStatus = new ArrayList<InterfaceBfdStatus>();
+ interfaceBfdStatus.add(new InterfaceBfdStatusBuilder().setBfdStatusKey(SouthboundUtils.BFD_OP_STATE).setBfdStatusValue(SouthboundUtils.BFD_STATE_UP).build());
+ List bfdStatusSpy = spy(interfaceBfdStatus);
+ when(newTerminationPoint.getInterfaceBfdStatus()).thenReturn(bfdStatusSpy);
+
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState = new InterfaceBuilder().setKey(new InterfaceKey(InterfaceManagerTestUtil.interfaceName)).build();
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> expectedInterface = Optional.of(ifState);
+
+ doReturn(Futures.immediateCheckedFuture(expectedInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
+ updateHelper.updateTunnelState(dataBroker, newTerminationPoint, null);
+
+ //verify
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
+ IfmUtil.buildStateInterfaceId(null);
+ InterfaceBuilder ifaceBuilder = new InterfaceBuilder().setOperStatus(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus.Up);
+ ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(null));
+ verify(mockWriteTx).merge(LogicalDatastoreType.OPERATIONAL, ifStateId, ifaceBuilder.build());
+
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.test;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+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.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigAddHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigRemoveHelper;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.OvsInterfaceConfigUpdateHelper;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+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.state.Interface.OperStatus;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.bridge.entry.BridgeInterfaceEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.math.BigInteger;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TunnelInterfaceConfigurationTest {
+ BigInteger dpId = BigInteger.valueOf(1);
+ NodeConnectorId nodeConnectorId = null;
+ NodeConnector nodeConnector = null;
+ Interface tunnelInterfaceEnabled = null;
+ Interface tunnelInterfaceDisabled = null;
+ ParentRefs parentRefs = null;
+ InstanceIdentifier<Interface> interfaceInstanceIdentifier = null;
+ InstanceIdentifier<NodeConnector> nodeConnectorInstanceIdentifier = null;
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceStateIdentifier = null;
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface stateInterface;
+
+ org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge.ref.info.BridgeRefEntryKey BridgeRefEntryKey;
+ InstanceIdentifier<BridgeRefEntry> dpnBridgeEntryIid = null;
+ BridgeEntryKey bridgeEntryKey = null;
+ BridgeEntry bridgeEntry = null;
+ InstanceIdentifier<BridgeEntry> bridgeEntryIid = null;
+ InstanceIdentifier<BridgeInterfaceEntry> bridgeInterfaceEntryInstanceIdentifier;
+ BridgeInterfaceEntry bridgeInterfaceEntry;
+ BridgeInterfaceEntryKey bridgeInterfaceEntryKey;
+ BridgeRefEntry bridgeRefEntry = null;
+ OvsdbBridgeAugmentation ovsdbBridgeAugmentation;
+ InstanceIdentifier<OvsdbBridgeAugmentation> ovsdbBridgeAugmentationInstanceIdentifier;
+ InstanceIdentifier<TerminationPoint> terminationPointInstanceIdentifier;
+ TerminationPoint terminationPoint;
+
+ @Mock DataBroker dataBroker;
+ @Mock IdManagerService idManager;
+ @Mock AlivenessMonitorService alivenessMonitorService;
+ @Mock ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
+ @Mock ReadOnlyTransaction mockReadTx;
+ @Mock WriteTransaction mockWriteTx;
+ @Mock
+ IMdsalApiManager mdsalApiManager;
+ OvsInterfaceConfigAddHelper addHelper;
+ OvsInterfaceConfigRemoveHelper removeHelper;
+ OvsInterfaceConfigUpdateHelper updateHelper;
+
+ @Before
+ public void setUp() throws Exception {
+ when(dataBroker.registerDataChangeListener(
+ any(LogicalDatastoreType.class),
+ any(InstanceIdentifier.class),
+ any(DataChangeListener.class),
+ any(DataChangeScope.class)))
+ .thenReturn(dataChangeListenerRegistration);
+ setupMocks();
+ }
+
+ private void setupMocks() {
+ nodeConnectorId = InterfaceManagerTestUtil.buildNodeConnectorId(BigInteger.valueOf(1), 2);
+ nodeConnector = InterfaceManagerTestUtil.buildNodeConnector(nodeConnectorId);
+ tunnelInterfaceEnabled = InterfaceManagerTestUtil.buildTunnelInterface(dpId, InterfaceManagerTestUtil.tunnelInterfaceName, "Test Interface1", true, TunnelTypeGre.class
+ , "192.168.56.101", "192.168.56.102");
+ tunnelInterfaceDisabled = InterfaceManagerTestUtil.buildTunnelInterface(dpId, InterfaceManagerTestUtil.tunnelInterfaceName, "Test Interface1", false, TunnelTypeGre.class
+ , "192.168.56.101", "192.168.56.102");
+ interfaceInstanceIdentifier = IfmUtil.buildId(InterfaceManagerTestUtil.tunnelInterfaceName);
+ nodeConnectorInstanceIdentifier = InterfaceManagerTestUtil.getNcIdent("openflow:1", nodeConnectorId);
+ interfaceStateIdentifier = IfmUtil.buildStateInterfaceId(tunnelInterfaceEnabled.getName());
+ stateInterface = InterfaceManagerTestUtil.buildStateInterface(InterfaceManagerTestUtil.tunnelInterfaceName, nodeConnectorId);
+ parentRefs = tunnelInterfaceEnabled.getAugmentation(ParentRefs.class);
+ BridgeRefEntryKey = new BridgeRefEntryKey(parentRefs.getDatapathNodeIdentifier());
+ dpnBridgeEntryIid = InterfaceMetaUtils.getBridgeRefEntryIdentifier(BridgeRefEntryKey);
+ bridgeEntryKey = new BridgeEntryKey(parentRefs.getDatapathNodeIdentifier());
+
+ bridgeInterfaceEntryKey = new BridgeInterfaceEntryKey(InterfaceManagerTestUtil.tunnelInterfaceName);
+ bridgeInterfaceEntryInstanceIdentifier = InterfaceMetaUtils.getBridgeInterfaceEntryIdentifier(bridgeEntryKey,
+ bridgeInterfaceEntryKey);
+ bridgeInterfaceEntry =
+ new BridgeInterfaceEntryBuilder().setKey(bridgeInterfaceEntryKey)
+ .setInterfaceName(tunnelInterfaceEnabled.getName()).build();
+
+ bridgeEntryIid = InterfaceMetaUtils.getBridgeEntryIdentifier(bridgeEntryKey);
+ bridgeEntry = InterfaceManagerTestUtil.buildBridgeEntry(dpId, bridgeInterfaceEntry);
+
+ Node node = new NodeBuilder().setKey(null).setNodeId(null).build();
+ ovsdbBridgeAugmentationInstanceIdentifier = InterfaceManagerTestUtil.getOvsdbAugmentationInstanceIdentifier(
+ InterfaceManagerTestUtil.tunnelInterfaceName, node);
+ ovsdbBridgeAugmentation = InterfaceManagerTestUtil.getOvsdbBridgeRef("s1");
+ bridgeRefEntry = new BridgeRefEntryBuilder().setKey(BridgeRefEntryKey).setDpid(dpId).
+ setBridgeReference(new OvsdbBridgeRef(ovsdbBridgeAugmentationInstanceIdentifier)).build();
+
+ terminationPointInstanceIdentifier = InterfaceManagerTestUtil.getTerminationPointId(ovsdbBridgeAugmentationInstanceIdentifier,
+ InterfaceManagerTestUtil.tunnelInterfaceName);
+ terminationPoint = InterfaceManagerTestUtil.getTerminationPoint(ovsdbBridgeAugmentationInstanceIdentifier, ovsdbBridgeAugmentation,
+ InterfaceManagerTestUtil.tunnelInterfaceName, 0, InterfaceTypeGre.class, tunnelInterfaceEnabled);
+ // Setup mocks
+ when(dataBroker.newReadOnlyTransaction()).thenReturn(mockReadTx);
+ when(dataBroker.newWriteOnlyTransaction()).thenReturn(mockWriteTx);
+ }
+
+ @Test
+ public void testAddGreInterfaceWhenSwitchIsNotConnected() {
+ Optional<Interface> expectedInterface = Optional.of(tunnelInterfaceEnabled);
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> expectedStateInterface = Optional.of(stateInterface);
+
+ doReturn(Futures.immediateCheckedFuture(expectedInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier);
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, dpnBridgeEntryIid);
+
+ addHelper.addConfiguration(dataBroker, parentRefs, tunnelInterfaceEnabled, idManager,
+ alivenessMonitorService, mdsalApiManager);
+
+ //Add some verifications
+ verify(mockWriteTx).put(LogicalDatastoreType.CONFIGURATION, bridgeInterfaceEntryInstanceIdentifier, bridgeInterfaceEntry, true);
+ }
+
+ @Test
+ public void testAddGreInterfaceWhenSwitchIsConnected() {
+ Optional<BridgeRefEntry> expectedBridgeRefEntry = Optional.of(bridgeRefEntry);
+ Optional<OvsdbBridgeAugmentation> expectedOvsdbBridgeAugmentation = Optional.of(ovsdbBridgeAugmentation);
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedBridgeRefEntry)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, dpnBridgeEntryIid);
+ doReturn(Futures.immediateCheckedFuture(expectedOvsdbBridgeAugmentation)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, ovsdbBridgeAugmentationInstanceIdentifier);
+
+ addHelper.addConfiguration(dataBroker, parentRefs, tunnelInterfaceEnabled, idManager,
+ alivenessMonitorService, mdsalApiManager);
+
+ //Add some verifications
+ verify(mockWriteTx).put(LogicalDatastoreType.CONFIGURATION, bridgeInterfaceEntryInstanceIdentifier ,
+ bridgeInterfaceEntry, true);
+ verify(mockWriteTx).put(LogicalDatastoreType.CONFIGURATION, terminationPointInstanceIdentifier ,
+ terminationPoint, true);
+ }
+
+
+ @Test
+ public void testDeleteGreInterfaceWhenSwitchIsConnected() {
+ Optional<BridgeRefEntry> expectedBridgeRefEntry = Optional.of(bridgeRefEntry);
+ Optional<BridgeEntry> expectedBridgeEntry = Optional.of(bridgeEntry);
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> expectedInterfaceState = Optional.of(stateInterface);
+ doReturn(Futures.immediateCheckedFuture(expectedBridgeRefEntry)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, dpnBridgeEntryIid);
+ doReturn(Futures.immediateCheckedFuture(expectedBridgeEntry)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, bridgeEntryIid);
+ doReturn(Futures.immediateCheckedFuture(expectedInterfaceState)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
+
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder ifaceBuilder = new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder();
+ ifaceBuilder.setOperStatus(OperStatus.Down);
+ ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(tunnelInterfaceEnabled.getName()));
+ stateInterface = ifaceBuilder.build();
+
+ removeHelper.removeConfiguration(dataBroker, alivenessMonitorService, tunnelInterfaceEnabled, idManager,
+ mdsalApiManager, parentRefs);
+
+ //Add some verifications
+ verify(mockWriteTx).delete(LogicalDatastoreType.CONFIGURATION, bridgeEntryIid);
+ verify(mockWriteTx).delete(LogicalDatastoreType.CONFIGURATION, terminationPointInstanceIdentifier);
+ }
+
+
+ @Test
+ public void testUpdateAdminStateForGreInterface() {
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface>
+ expectedStateInterface = Optional.of(stateInterface);
+ doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
+
+ updateHelper.updateConfiguration(dataBroker, alivenessMonitorService, idManager, mdsalApiManager,
+ tunnelInterfaceDisabled,tunnelInterfaceEnabled);
+
+ //verify whether operational data store is updated with the new oper state.
+ InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
+ ifaceBuilder.setOperStatus(OperStatus.Down);
+ ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(stateInterface.getName()));
+
+ verify(mockWriteTx).merge(LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier,
+ ifaceBuilder.build());
+ }
+ @Test
+ public void testEnableAdminStateForGreInterface() {
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface>
+ expectedStateInterface = Optional.of(stateInterface);
+ Optional<NodeConnector>expectedNodeConnector = Optional.of(nodeConnector);
+
+ doReturn(Futures.immediateCheckedFuture(expectedNodeConnector)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, nodeConnectorInstanceIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
+
+ updateHelper.updateConfiguration(dataBroker, alivenessMonitorService, idManager, mdsalApiManager,
+ tunnelInterfaceEnabled,tunnelInterfaceDisabled);
+
+ //verify whether operational data store is updated with the new oper state.
+ InterfaceBuilder ifaceBuilder = new InterfaceBuilder();
+ ifaceBuilder.setOperStatus(OperStatus.Down);
+ ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(stateInterface.getName()));
+
+ verify(mockWriteTx).merge(LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier,
+ ifaceBuilder.build());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.test;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+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.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.idmanager.IdManager;
+import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
+import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers.*;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+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.ietf.interfaces.rev140508.interfaces.Interface;
+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.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class VlanInterfaceConfigurationTest {
+
+ @Mock
+ DataBroker dataBroker;
+ @Mock
+ AlivenessMonitorService alivenessMonitorService;
+ @Mock IdManager idManager;
+ @Mock ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
+ @Mock ReadOnlyTransaction mockReadTx;
+ @Mock WriteTransaction mockWriteTx;
+ @Mock IMdsalApiManager mdsalApiManager;
+ OvsInterfaceConfigAddHelper addHelper;
+ OvsInterfaceConfigRemoveHelper removeHelper;
+ OvsVlanMemberConfigAddHelper memberConfigAddHelper;
+ OvsVlanMemberConfigRemoveHelper memberConfigRemoveHelper;
+ OvsVlanMemberConfigUpdateHelper memberConfigUpdateHelper;
+
+ NodeConnectorId nodeConnectorId;
+ NodeConnector nodeConnector;
+ Interface vlanInterfaceEnabled;
+ Interface vlanInterfaceDisabled;
+ InstanceIdentifier<Interface> interfaceInstanceIdentifier;
+ InstanceIdentifier<NodeConnector> nodeConnectorInstanceIdentifier;
+ InstanceIdentifier<InterfaceParentEntry> interfaceParentEntryIdentifier = null;
+ InterfaceParentEntry interfaceParentEntry;
+ InterfaceChildEntry interfaceChildEntry = null;
+ InstanceIdentifier<InterfaceChildEntry> interfaceChildEntryInstanceIdentifier;
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceStateIdentifier;
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface stateInterface;
+
+ @Before
+ public void setUp() throws Exception {
+ when(dataBroker.registerDataChangeListener(
+ any(LogicalDatastoreType.class),
+ any(InstanceIdentifier.class),
+ any(DataChangeListener.class),
+ any(DataChangeScope.class)))
+ .thenReturn(dataChangeListenerRegistration);
+ setupMocks();
+ }
+
+ @After
+ public void cleanUp(){
+ }
+
+ private void setupMocks() {
+ nodeConnectorId = InterfaceManagerTestUtil.buildNodeConnectorId(BigInteger.valueOf(1), 1);
+ nodeConnector = InterfaceManagerTestUtil.buildNodeConnector(nodeConnectorId);
+ vlanInterfaceEnabled = InterfaceManagerTestUtil.buildInterface(InterfaceManagerTestUtil.interfaceName, "Test Vlan Interface1", true, L2vlan.class, BigInteger.valueOf(1));
+ vlanInterfaceDisabled = InterfaceManagerTestUtil.buildInterface(InterfaceManagerTestUtil.interfaceName, "Test Vlan Interface1", false, L2vlan.class, BigInteger.valueOf(1));
+ interfaceInstanceIdentifier = IfmUtil.buildId(InterfaceManagerTestUtil.interfaceName);
+ nodeConnectorInstanceIdentifier = InterfaceManagerTestUtil.getNcIdent("openflow:1", nodeConnectorId);
+ interfaceStateIdentifier = IfmUtil.buildStateInterfaceId(vlanInterfaceEnabled.getName());
+ stateInterface = InterfaceManagerTestUtil.buildStateInterface(InterfaceManagerTestUtil.interfaceName, nodeConnectorId);
+ AllocateIdOutput output = new AllocateIdOutputBuilder().setIdValue((long)1).build();
+ RpcResultBuilder<AllocateIdOutput> allocateIdRpcBuilder = RpcResultBuilder.success();
+ allocateIdRpcBuilder.withResult(output);
+ ListenableFuture<RpcResult<AllocateIdOutput>> future = Futures.immediateFuture(allocateIdRpcBuilder.build());
+ interfaceParentEntryIdentifier = InterfaceMetaUtils.getInterfaceParentEntryIdentifier(
+ new InterfaceParentEntryKey(InterfaceManagerTestUtil.interfaceName));
+ interfaceChildEntryInstanceIdentifier = InterfaceMetaUtils.getInterfaceChildEntryIdentifier(new InterfaceParentEntryKey("s1-eth1"),
+ new InterfaceChildEntryKey(vlanInterfaceEnabled.getName()));
+ interfaceChildEntry = new InterfaceChildEntryBuilder().setKey(new InterfaceChildEntryKey(vlanInterfaceEnabled.getName())).
+ setChildInterface(vlanInterfaceEnabled.getName()).build();
+
+ InterfaceParentEntryBuilder ifaceParentEntryBuilder = new InterfaceParentEntryBuilder();
+ List<InterfaceChildEntry> ifaceChildEntryList= new ArrayList<>();
+ ifaceChildEntryList.add(interfaceChildEntry);
+ interfaceParentEntry = ifaceParentEntryBuilder.setInterfaceChildEntry(ifaceChildEntryList).build();
+
+ // Setup mocks
+ when(dataBroker.newReadOnlyTransaction()).thenReturn(mockReadTx);
+ when(dataBroker.newWriteOnlyTransaction()).thenReturn(mockWriteTx);
+
+ when(idManager.allocateId(any(AllocateIdInput.class))).thenReturn(future);
+ }
+
+ @Test
+ public void testAddVlanInterfaceWhenSwitchIsNotConnected() {
+ Optional<Interface> expectedInterface = Optional.of(vlanInterfaceEnabled);
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> expectedStateInterface = Optional.of(stateInterface);
+
+ doReturn(Futures.immediateCheckedFuture(expectedInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier);
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceParentEntryIdentifier);
+
+ addHelper.addConfiguration(dataBroker, vlanInterfaceEnabled.getAugmentation(ParentRefs.class), vlanInterfaceEnabled, idManager,
+ alivenessMonitorService, mdsalApiManager);
+
+ //Nothing to verify, since when switch is not connected we don't do any datastore operation
+
+ }
+
+ @Test
+ public void testAddVlanInterfaceWhenSwitchIsConnected() {
+ Optional<Interface> expectedInterface = Optional.of(vlanInterfaceEnabled);
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface>
+ expectedStateInterface = Optional.of(stateInterface);
+
+ doReturn(Futures.immediateCheckedFuture(expectedInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceParentEntryIdentifier);
+
+ addHelper.addConfiguration(dataBroker, vlanInterfaceEnabled.getAugmentation(ParentRefs.class), vlanInterfaceEnabled, idManager,
+ alivenessMonitorService, mdsalApiManager);
+
+ //Nothing to verify, since when adminstate is enabled and switch opstate is already up,
+ //we don't do any datastore operation
+ }
+
+ @Test
+ public void testAddVlanInterfaceWhenAdminStateDisabled() {
+ Optional<Interface> expectedInterface = Optional.of(vlanInterfaceEnabled);
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> expectedStateInterface =
+ Optional.of(stateInterface);
+
+ doReturn(Futures.immediateCheckedFuture(expectedInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceParentEntryIdentifier);
+
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder ifaceBuilder = new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder();
+ ifaceBuilder.setOperStatus(OperStatus.Down);
+ ifaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(vlanInterfaceEnabled.getName()));
+ ifaceBuilder.setType(L2vlan.class);
+ stateInterface = ifaceBuilder.build();
+
+ addHelper.addConfiguration(dataBroker, vlanInterfaceDisabled.getAugmentation(ParentRefs.class), vlanInterfaceDisabled, idManager,
+ alivenessMonitorService, mdsalApiManager);
+
+ //verification
+ verify(mockWriteTx).put(LogicalDatastoreType.CONFIGURATION, interfaceChildEntryInstanceIdentifier, interfaceChildEntry, true);
+ }
+
+ @Test
+ public void testDeleteVlanInterface() {
+ Optional<Interface> expected = Optional.of(vlanInterfaceEnabled);
+ Optional<NodeConnector> expectedNc = Optional.of(nodeConnector);
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> expectedStateIf = Optional.of(stateInterface);
+ doReturn(Futures.immediateCheckedFuture(expected)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedNc)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, nodeConnectorInstanceIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedStateIf)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceParentEntryIdentifier);
+
+ removeHelper.removeConfiguration(dataBroker,alivenessMonitorService, vlanInterfaceEnabled, idManager,
+ mdsalApiManager, vlanInterfaceEnabled.getAugmentation(ParentRefs.class));
+
+ //verification
+ verify(mockWriteTx).delete(LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
+ }
+
+ @Test
+ public void testAddMemberConfiguration(){
+
+ Optional<Interface> expectedInterface = Optional.of(vlanInterfaceEnabled);
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> expectedStateInterface = Optional.of(stateInterface);
+
+ doReturn(Futures.immediateCheckedFuture(expectedInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
+
+ memberConfigAddHelper.addConfiguration(dataBroker, vlanInterfaceEnabled.getAugmentation(ParentRefs.class), vlanInterfaceEnabled, null, idManager);
+ }
+
+ @Test
+ public void testRemoveMemberConfiguration(){
+
+ Optional<InterfaceParentEntry> expectedParentEntry = Optional.of(interfaceParentEntry);
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> expectedStateInterface = Optional.of(stateInterface);
+
+ doReturn(Futures.immediateCheckedFuture(expectedParentEntry)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceParentEntryIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
+
+ memberConfigRemoveHelper.removeConfiguration(dataBroker, vlanInterfaceEnabled.getAugmentation(ParentRefs.class), vlanInterfaceEnabled, null, idManager);
+ }
+
+ @Test
+ public void testUpdateMemberConfiguration(){
+
+ Optional<InterfaceChildEntry> expectedChildEntry = Optional.of(interfaceChildEntry);
+ Optional<InterfaceParentEntry> expectedParentEntry = Optional.of(interfaceParentEntry);
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> expectedStateInterface = Optional.of(stateInterface);
+ Optional<Interface> expectedInterface = Optional.of(vlanInterfaceEnabled);
+
+ doReturn(Futures.immediateCheckedFuture(expectedChildEntry)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceChildEntryInstanceIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedParentEntry)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceParentEntryIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedStateInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.OPERATIONAL, interfaceStateIdentifier);
+ doReturn(Futures.immediateCheckedFuture(expectedInterface)).when(mockReadTx).read(
+ LogicalDatastoreType.CONFIGURATION, interfaceInstanceIdentifier);
+
+ memberConfigUpdateHelper.updateConfiguration(dataBroker, alivenessMonitorService, vlanInterfaceEnabled.getAugmentation(ParentRefs.class), vlanInterfaceDisabled, vlanInterfaceEnabled.getAugmentation(IfL2vlan.class), vlanInterfaceEnabled, idManager, mdsalApiManager);
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: --><!--
+Copyright (c) 2015 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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>interfacemgr-shell</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>interfacemgr-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>interfacemgr-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.console</artifactId>
+ <version>${karaf.shell.console.version}</version>
+ </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.vpnservice.interfacemgr.shell;
+
+import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
+import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo.InterfaceOpState;
+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.vpnservice.interfacemgr.rev150331.IfL2vlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+
+import java.util.Formatter;
+
+public class IfmCLIUtil {
+ private static final String VLAN_OUTPUT_FORMAT_LINE1 = "%-55s";
+ private static final String VLAN_OUTPUT_FORMAT = "%-24s %-20s %-15s %-24s";
+ private static final String VXLAN_OUTPUT_FORMAT = "%-24s %-24s %-18s %-5s";
+ private static final String VXLAN_OUTPUT_FORMAT_LINE1 = "%-49s %-45s";
+ private static final String UNSET = "N/A";
+
+ public static void showVlanHeaderOutput() {
+ StringBuilder sb = new StringBuilder();
+ Formatter fmt = new Formatter(sb);
+ System.out.println(fmt.format(VLAN_OUTPUT_FORMAT_LINE1, "Name"));
+ sb.setLength(0);
+ System.out.println(fmt.format(VLAN_OUTPUT_FORMAT, "", "Dpn", "PortName",
+ "Vlan-Id"));
+ sb.setLength(0);
+ System.out.println(fmt.format(VLAN_OUTPUT_FORMAT, "Tag", "PortNo",
+ "AdmState", "OpState"));
+ sb.setLength(0);
+ System.out.println(fmt.format(VLAN_OUTPUT_FORMAT, "Description", "", "", ""));
+ sb.setLength(0);
+ System.out.println(fmt.format("--------------------------------------------------------------------------------"));
+ sb.setLength(0);
+ fmt.close();
+ }
+
+ public static void showVlanOutput(InterfaceInfo ifaceInfo, Interface iface) {
+ StringBuilder sb = new StringBuilder();
+ Formatter fmt = new Formatter(sb);
+ IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
+ int vlanId = l2vlan != null ? l2vlan.getVlanId() != null ? l2vlan.getVlanId().getValue() : 0 : 0;
+ System.out.println(fmt.format(VLAN_OUTPUT_FORMAT_LINE1,
+ iface.getName()));
+ sb.setLength(0);
+ System.out.println(fmt.format(VLAN_OUTPUT_FORMAT,
+ "", (ifaceInfo == null) ? UNSET : ifaceInfo.getDpId(),
+ (ifaceInfo == null) ? UNSET : ifaceInfo.getPortName(), vlanId));
+ sb.setLength(0);
+ System.out.println(fmt.format(VLAN_OUTPUT_FORMAT,
+ (ifaceInfo == null) ? UNSET : ifaceInfo.getInterfaceTag(),
+ (ifaceInfo == null) ? UNSET : ifaceInfo.getPortNo(),
+ (ifaceInfo == null) ? UNSET : ifaceInfo.getAdminState(),
+ (ifaceInfo == null) ? UNSET : ifaceInfo.getOpState()));
+ sb.setLength(0);
+ System.out.println(fmt.format(VLAN_OUTPUT_FORMAT + "\n",
+ iface.getDescription(), "", "", ""));
+ sb.setLength(0);
+ fmt.close();
+ }
+
+ public static void showVxlanHeaderOutput() {
+ StringBuilder sb = new StringBuilder();
+ Formatter fmt = new Formatter(sb);
+ System.out.println(fmt
+ .format(VXLAN_OUTPUT_FORMAT_LINE1, "Name", "Description"));
+ sb.setLength(0);
+ System.out.println(fmt.format(VXLAN_OUTPUT_FORMAT, "Local IP",
+ "Remote IP", "Gateway IP", "AdmState"));
+ sb.setLength(0);
+ System.out.println(fmt.format(VXLAN_OUTPUT_FORMAT, "OpState", "Parent",
+ "Tag", ""));
+ sb.setLength(0);
+ System.out.println(fmt
+ .format("--------------------------------------------------------------------------------"));
+ fmt.close();
+ }
+
+ public static void showVxlanOutput(Interface iface, InterfaceInfo interfaceInfo) {
+ StringBuilder sb = new StringBuilder();
+ Formatter fmt = new Formatter(sb);
+ System.out.println(fmt.format(VXLAN_OUTPUT_FORMAT_LINE1,
+ iface.getName(),
+ iface.getDescription() == null ? UNSET : iface.getDescription()));
+ sb.setLength(0);
+ IfTunnel ifTunnel = iface.getAugmentation(IfTunnel.class);
+ System.out.println(fmt.format(VXLAN_OUTPUT_FORMAT,
+ ifTunnel.getTunnelSource().getIpv4Address().getValue(),
+ ifTunnel.getTunnelDestination().getIpv4Address().getValue(),
+ ifTunnel.getTunnelGateway() == null ? UNSET : ifTunnel.getTunnelGateway().getIpv4Address().getValue(),
+ (interfaceInfo == null) ? InterfaceInfo.InterfaceAdminState.DISABLED : interfaceInfo.getAdminState()));
+ sb.setLength(0);
+ ParentRefs parentRefs = iface.getAugmentation(ParentRefs.class);
+ System.out.println(fmt.format(VXLAN_OUTPUT_FORMAT + "\n",
+ (interfaceInfo == null) ? InterfaceOpState.DOWN : interfaceInfo.getOpState(),
+ String.format("%s/%s", parentRefs.getDatapathNodeIdentifier(),
+ iface.getName()),
+ (interfaceInfo == null) ? UNSET : interfaceInfo.getInterfaceTag(), ""));
+ fmt.close();
+ }
+}
--- /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.shell;
+
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
+import org.opendaylight.vpnservice.interfacemgr.globals.VlanInterfaceInfo;
+import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
+import org.opendaylight.vpnservice.interfacemgr.shell.IfmCLIUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+@Command(scope = "vlan", name = "show", description = "view the configured vlan ports")
+public class ShowVlan extends OsgiCommandSupport {
+ private static final Logger logger = LoggerFactory.getLogger(ShowVlan.class);
+ private IInterfaceManager interfaceManager;
+
+ public void setInterfaceManager(IInterfaceManager interfaceManager) {
+ this.interfaceManager = interfaceManager;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ logger.debug("Executing show VLAN command");
+ List<Interface> vlanList = interfaceManager.getVlanInterfaces();
+ if (!vlanList.isEmpty()) {
+ IfmCLIUtil.showVlanHeaderOutput();
+ }
+ for (Interface iface : vlanList) {
+ InterfaceInfo ifaceState = interfaceManager.getInterfaceInfoFromOperationalDataStore(iface.getName());
+ IfmCLIUtil.showVlanOutput(ifaceState, iface);
+ }
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 - 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.shell;
+
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
+import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
+import org.opendaylight.vpnservice.interfacemgr.shell.IfmCLIUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+@Command(scope = "vxlan", name = "show", description = "view the configured vxlan ports")
+public class ShowVxlan extends OsgiCommandSupport {
+ private static final Logger logger = LoggerFactory.getLogger(ShowVxlan.class);
+ private IInterfaceManager interfaceManager;
+ private DataBroker dataBroker;
+
+ public void setInterfaceManager(IInterfaceManager interfaceManager) {
+ this.interfaceManager = interfaceManager;
+ }
+
+ public void setDataBroker(DataBroker dataBroker){
+ this.dataBroker = dataBroker;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ logger.debug("Executing show Vxlan command");
+ List<Interface> vxlanList = interfaceManager.getVxlanInterfaces();
+ if (!vxlanList.isEmpty()) {
+ IfmCLIUtil.showVxlanHeaderOutput();
+ }
+ for (Interface iface : vxlanList) {
+ InterfaceInfo ifaceState = interfaceManager.getInterfaceInfoFromOperationalDataStore(iface.getName());
+ IfmCLIUtil.showVxlanOutput(iface, ifaceState);
+ }
+ 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
+-->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+ <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.interfacemgr.shell.ShowVlan">
+ <property name="interfaceManager" ref="interfaceManagerRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.interfacemgr.shell.ShowVxlan">
+ <property name="interfaceManager" ref="interfaceManagerRef" />
+ </action>
+ </command>
+ </command-bundle>
+</blueprint>
--- /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.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>interfacemgr-aggregator</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <name>interfacemgr</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>interfacemgr-api</module>
+ <module>interfacemgr-impl</module>
+ <module>interfacemgr-shell</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>
--- /dev/null
+/target/
+/target/
+/target/
+/target/
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>itm-api</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>interfacemgr-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <!--
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-inet-types</artifactId>
+ <version>2010.09.24.9-SNAPSHOT</version>
+ </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>
+ </dependencies>
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2015 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.itm.api;
+import java.math.BigInteger;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.vpnservice.interfacemgr.exceptions.InterfaceNotFoundException;
+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.inet.types.rev100924.IpAddress;
+//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.rev151102.vtep.config.schemas.VtepConfigSchema;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.VtepConfigSchema;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList ;
+
+public interface IITMProvider {
+ // APIs used by i
+ public void createLocalCache(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask, String gatewayIp, String transportZone);
+
+ public void commitTeps();
+
+ public DataBroker getDataBroker();
+
+ public void showTeps();
+ public void showState(TunnelList tunnels);
+
+ public void deleteVtep(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask,
+ String gatewayIp, String transportZone);
+ // public void showState(TunnelsState tunnelsState);
+ public void configureTunnelType(String transportZone, String tunnelType);
+
+
+ /**
+ * Adds the vtep config schema.
+ *
+ * @param vtepConfigSchema
+ * the vtep config schema
+ */
+ public void addVtepConfigSchema(VtepConfigSchema vtepConfigSchema);
+
+ /**
+ * Gets the vtep config schema.
+ *
+ * @param schemaName
+ * the schema name
+ * @return the vtep config schema
+ */
+ public VtepConfigSchema getVtepConfigSchema(String schemaName);
+
+ /**
+ * Gets the all vtep config schemas.
+ *
+ * @return the all vtep config schemas
+ */
+ public List<VtepConfigSchema> getAllVtepConfigSchemas();
+
+ /**
+ * Update VTEP schema.
+ *
+ * @param schemaName
+ * the schema name
+ * @param lstDpnsForAdd
+ * the lst dpns for add
+ * @param lstDpnsForDelete
+ * the lst dpns for delete
+ */
+ public void updateVtepSchema(String schemaName, List<BigInteger> lstDpnsForAdd, List<BigInteger> lstDpnsForDelete);
+
+ /**
+ * Delete all vtep schemas.
+ */
+ public void deleteAllVtepSchemas();
+
+ public void configureTunnelMonitorEnabled(boolean monitorEnabled);
+
+ public void configureTunnelMonitorInterval(int interval);
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.itm.globals;
+
+import java.math.BigInteger;
+
+public class ITMConstants{
+ public static final BigInteger COOKIE_ITM = new BigInteger("9000000", 16);
+ public static final BigInteger COOKIE_ITM_EXTERNAL = new BigInteger("9050000", 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 int LLDP_SERVICE_ID = 0;
+ //Tunnel Monitoring
+ public static final boolean DEFAULT_MONITOR_ENABLED = true;
+ public static final int DEFAULT_MONITOR_INTERVAL = 10;
+ public static final int BFD_DEFAULT_MONITOR_INTERVAL = 100;
+ public static final String DUMMY_IP_ADDRESS = "0.0.0.0";
+ public static final String TUNNEL_TYPE_VXLAN = "VXLAN";
+ public static final String TUNNEL_TYPE_GRE = "GRE";
+ public static final String TUNNEL_TYPE_MPLS_OVER_GRE = "MPLS_OVER_GRE";
+ public static final String TUNNEL_TYPE_INVALID = "Invalid";
+}
+
--- /dev/null
+module itm-config {
+
+ namespace "urn:opendaylight:vpnservice:itm:config";
+
+ prefix itm-config;
+
+ import ietf-interfaces {
+ prefix if;
+ }
+ import ietf-yang-types {
+ prefix yang;
+ }
+ import ietf-inet-types {
+ prefix inet;
+ revision-date "2010-09-24";
+ }
+ import odl-interface {
+ prefix odlif;
+ }
+ import config { prefix config; revision-date 2013-04-05; }
+
+ description "This YANG module defines automatic tunnel configuration.";
+ revision "2015-11-02";
+
+ /* Tunnel Monitoring Knob */
+
+ container tunnel-monitor-enabled {
+ leaf enabled {
+ type boolean;
+ default true;
+ }
+ }
+
+ container tunnel-monitor-interval {
+ leaf interval {
+ type uint16 {
+ range "5..30";
+ }
+ default 10;
+ }
+ }
+
+ /* Configuration data */
+
+ container vtep-config-schemas {
+ list vtep-config-schema {
+ key schema-name;
+ leaf schema-name {
+ type string;
+ mandatory true;
+ description "Schema name";
+ }
+ leaf transport-zone-name {
+ type string;
+ mandatory true;
+ description "Transport zone";
+ }
+ leaf tunnel-type {
+ type identityref {
+ base odlif:tunnel-type-base;
+ }
+ }
+ leaf port-name {
+ type string;
+ mandatory true;
+ description "Port name";
+ }
+ leaf vlan-id {
+ type uint16 {
+ range "0..4094";
+ }
+ mandatory true;
+ description "VLAN ID";
+ }
+ leaf gateway-ip {
+ type inet:ip-address;
+ description "Gateway IP address";
+ }
+ leaf subnet {
+ type inet:ip-prefix;
+ mandatory true;
+ description "Subnet Mask in CIDR-notation string, e.g. 10.0.0.0/24";
+ }
+ leaf exclude-ip-filter {
+ type string;
+ description "IP Addresses which needs to be excluded from the specified subnet. IP address range or comma separated IP addresses can to be specified. e.g: 10.0.0.1-10.0.0.20,10.0.0.30,10.0.0.35";
+ }
+ list dpn-ids {
+ key "DPN";
+ leaf DPN {
+ type uint64;
+ description "DPN ID";
+ }
+ }
+ }
+ }
+
+ /* Ip Address book keeping */
+ container vtep-ip-pools {
+ config true;
+ list vtep-ip-pool {
+ key subnet-cidr;
+ leaf subnet-cidr{
+ type string;
+ }
+ leaf-list available-ipaddress {
+ type inet:ip-address;
+ }
+ leaf-list allocated-ipaddress {
+ type inet:ip-address;
+ }
+ }
+ }
+}
--- /dev/null
+module itm-rpc {
+ namespace "urn:opendaylight:vpnservice:itm:rpcs";
+ prefix "itmrpcs";
+
+ import ietf-inet-types {
+ prefix inet;
+ revision-date "2010-09-24";
+ }
+
+ import ietf-yang-types {
+ prefix yang;
+ }
+
+ import ietf-interfaces {
+ prefix if; revision-date 2014-05-08;
+ }
+
+ import odl-interface {
+ prefix odlif;
+ revision-date "2015-03-31";
+ }
+
+ import opendaylight-action-types {prefix action;revision-date "2013-11-12";}
+ import opendaylight-flow-types {prefix offlow;revision-date "2013-10-26";}
+
+
+ revision "2015-12-17" {
+ description "ODL Specific Itm Manager Rpcs Module";
+ }
+
+ /* RPCs */
+
+ rpc get-tunnel-interface-name {
+ description "used to retrieve tunnel interface id between Dpns";
+ input {
+ leaf source-dpid {
+ type uint64;
+ }
+ leaf destination-dpid {
+ type uint64;
+ }
+ leaf tunnel-type {
+ type identityref {
+ base odlif:tunnel-type-base;
+ }
+ }
+ }
+ output {
+ leaf interface-name {
+ type string;
+ }
+ }
+ }
+
+ rpc get-internal-or-external-interface-name {
+ description "used to retrieve tunnel interface id with src Dpn and destination ip";
+ input {
+ leaf source-dpid {
+ type uint64;
+ }
+ leaf destination-ip {
+ type inet:ip-address;
+ }
+ leaf tunnel-type {
+ type identityref {
+ base odlif:tunnel-type-base;
+ }
+ }
+ }
+ output {
+ leaf interface-name {
+ type string;
+ }
+ }
+ }
+
+ rpc get-external-tunnel-interface-name {
+ description "used to retrieve external tunnel interface id between Dpns/TORs";
+ input {
+ leaf source-node {
+ type string;
+ }
+ leaf destination-node {
+ type string;
+ }
+ leaf tunnel-type {
+ type identityref {
+ base odlif:tunnel-type-base;
+ }
+ }
+ }
+ output {
+ leaf interface-name {
+ type string;
+ }
+ }
+ }
+
+ rpc build-external-tunnel-from-dpns {
+ description "used for building tunnels between a Dpn and external node";
+ input {
+ leaf-list dpn-id {
+ type uint64;
+ }
+ leaf destination-ip {
+ type inet:ip-address;
+ }
+ leaf tunnel-type {
+ type identityref {
+ base odlif:tunnel-type-base;
+ }
+ }
+ }
+ }
+
+ rpc add-external-tunnel-endpoint {
+ description "used for building tunnels between teps on all Dpns and external node";
+ input {
+ leaf destination-ip {
+ type inet:ip-address;
+ }
+ leaf tunnel-type {
+ type identityref {
+ base odlif:tunnel-type-base;
+ }
+ }
+ }
+ }
+ rpc remove-external-tunnel-from-dpns {
+ description "used for building tunnels between a Dpn and external node";
+ input {
+ leaf-list dpn-id {
+ type uint64;
+ }
+ leaf destination-ip {
+ type inet:ip-address;
+ }
+ leaf tunnel-type {
+ type identityref {
+ base odlif:tunnel-type-base;
+ }
+ }
+ }
+ }
+
+ rpc remove-external-tunnel-endpoint {
+ description "used for building tunnels between teps on all Dpns and external node";
+ input {
+ leaf destination-ip {
+ type inet:ip-address;
+ }
+ leaf tunnel-type {
+ type identityref {
+ base odlif:tunnel-type-base;
+ }
+ }
+ }
+ }
+
+ rpc create-terminating-service-actions {
+ description "used for programming the terminating service actions";
+ input {
+ leaf dpn-id {
+ type uint64;
+ }
+ leaf service-id {
+ type uint16;
+ }
+ uses offlow:instruction-list;
+ }
+ }
+
+ rpc remove-terminating-service-actions {
+ description "used for removing the terminating service actions";
+ input {
+ leaf dpn-id {
+ type uint64;
+ }
+ leaf service-id {
+ type uint16;
+ }
+ }
+ }
+
+ rpc add-l2-gw-device {
+ description "used for building tunnels between teps on all Dpns and hwVtep";
+ input {
+ leaf topology-id {
+ type string;
+ }
+ leaf node-id {
+ type string;
+ }
+ leaf ip-address {
+ type inet:ip-address;
+ }
+ }
+ }
+
+ rpc add-l2-gw-mlag-device {
+ description "used for building tunnels between teps on all Dpns and hwVtep";
+ input {
+ leaf topology-id {
+ type string;
+ }
+ leaf-list node-id {
+ type string;
+ }
+ leaf ip-address {
+ type inet:ip-address;
+ }
+ }
+ }
+ rpc delete-l2-gw-device {
+ description "used for deleting tunnels between teps on all Dpns and hwVtep";
+ input {
+ leaf topology-id {
+ type string;
+ }
+ leaf node-id {
+ type string;
+ }
+ leaf ip-address {
+ type inet:ip-address;
+ }
+ }
+ }
+
+ rpc delete-l2-gw-mlag-device {
+ description "used for deleting tunnels between teps on all Dpns and hwVtep";
+ input {
+ leaf topology-id {
+ type string;
+ }
+ leaf-list node-id {
+ type string;
+ }
+ leaf ip-address {
+ type inet:ip-address;
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+module itm-state {
+
+ namespace "urn:opendaylight:vpnservice:itm:op";
+
+ prefix itm-state;
+
+ import ietf-interfaces {
+ prefix if;
+ }
+
+ import ietf-yang-types {
+ prefix yang;
+ }
+
+ import ietf-inet-types {
+ prefix inet;
+ revision-date "2010-09-24";
+ }
+ import odl-interface {
+ prefix odlif; revision-date "2015-03-31";
+ }
+
+
+ description "This YANG module defines operation part of the model.";
+
+ revision "2015-07-01";
+
+ /* Operational state */
+
+ identity tep-type-base {
+ description "Base TEP device type";
+ }
+ identity tep-type-internal {
+ base tep-type-base;
+ description "TEP type internal e.g. Compute OVS";
+ }
+ identity tep-type-external {
+ base tep-type-base;
+ description "TEP type external e.g. DC Gateway";
+ }
+ identity tep-type-hwvtep {
+ base tep-type-base;
+ description "TEP type Hwvtep e.g. TOR devices";
+ }
+ typedef tep-type {
+ type identityref {
+ base tep-type-base;
+ }
+ description "This type is used to refer to an TEP Device Type.";
+ }
+ container dpn-endpoints {
+
+ list DPN-TEPs-info {
+
+ key "DPN-ID";
+
+ leaf DPN-ID {
+ type uint64;
+ }
+ leaf up {
+ type boolean;
+ config false;
+ }
+
+ /* Minimum 1 port. We may for now support only two ports */
+ list tunnel-end-points {
+ ordered-by user;
+ key "portname VLAN-ID ip-address tunnel-type"; /* Multiple tunnels on the same physical port but on different VLAN can be supported */
+
+ leaf portname {
+ type string;
+ }
+ leaf VLAN-ID {
+ type uint16;
+ }
+ leaf ip-address {
+ type inet:ip-address;
+ }
+ leaf subnet-mask {
+ type inet:ip-prefix;
+ }
+ leaf gw-ip-address {
+ type inet:ip-address;
+ }
+ leaf transport-zone {
+ type string;
+ }
+ leaf interface-name {
+ type string;
+ }
+ leaf tunnel-type {
+ type identityref {
+ base odlif:tunnel-type-base;
+ }
+ }
+ }
+
+ }
+ }
+
+
+ container tunnel-list {
+ list internal-tunnel {
+
+ key "source-DPN destination-DPN transport-type";
+
+ leaf source-DPN {
+ type uint64;
+ }
+
+ leaf destination-DPN {
+ type uint64;
+ }
+ leaf transport-type {
+ type identityref {
+ base odlif:tunnel-type-base;
+ }
+ }
+
+ /* logical-group interface id */
+
+ leaf tunnel-interface-name {
+ type string;
+ }
+ }
+ }
+
+ container external-tunnel-list {
+ list external-tunnel {
+
+ key "source-device destination-device transport-type";
+
+ leaf source-device {
+ type string; //dpnid or node-id
+ }
+
+ leaf destination-device {
+ type string; //dpn-id or node-id or ip
+ }
+
+ leaf transport-type {
+ type identityref {
+ base odlif:tunnel-type-base;
+ }
+ }
+ /* logical-group interface id */
+
+ leaf tunnel-interface-name {
+ type string;
+ }
+
+ }
+ }
+
+ grouping tep-info-attributes {
+ leaf tep-device-type {
+ type identityref {
+ base tep-type-base;
+ }
+ }
+ leaf tep-device-id {
+ type string; //dpnid or node-id
+ }
+ leaf tep-ip {
+ type inet:ip-address; //dpnid or node-id
+ }
+ }
+
+ container tunnels_state {
+ list state-tunnel-list {
+ key "tunnel-interface-name";
+ leaf tunnel-interface-name {
+ type string;
+ }
+ leaf tunnel-state {
+ type boolean;
+ config false;
+ }
+ container src-info {
+ uses tep-info-attributes;
+ }
+ container dst-info {
+ uses tep-info-attributes;
+ }
+ leaf transport-type {
+ type identityref {
+ base odlif:tunnel-type-base;
+ }
+ }
+ }
+ }
+ notification itm-tunnel-build-complete{
+ }
+
+}
--- /dev/null
+module itm {
+
+ namespace "urn:opendaylight:vpnservice:itm";
+
+ prefix itm;
+
+ import ietf-interfaces {
+ prefix if;
+ }
+ import ietf-yang-types {
+ prefix yang;
+ }
+ import ietf-inet-types {
+ prefix inet;
+ revision-date "2010-09-24";
+ }
+
+ import odl-interface {
+ prefix odlif;
+ }
+
+
+ import config { prefix config; revision-date 2013-04-05; }
+
+ description "This YANG module defines tunnel configuration.";
+ revision "2015-07-01";
+
+ /* Configuration data */
+
+ container transport-zones {
+ list transport-zone {
+ ordered-by user;
+ key zone-name;
+ leaf zone-name {
+ type string;
+ }
+ leaf tunnel-type {
+ type identityref {
+ base odlif:tunnel-type-base;
+ }
+ }
+
+ list subnets {
+ key "prefix";
+ leaf prefix {
+ type inet:ip-prefix;
+ }
+ leaf gateway-ip {
+ type inet:ip-address;
+ }
+ leaf vlan-id {
+ type uint16{
+ range "0..4094";
+ }
+ }
+ list vteps {
+ key "dpn-id portname";
+ leaf dpn-id {
+ type uint64;
+ }
+ leaf portname {
+ type string;
+ }
+ leaf ip-address {
+ type inet:ip-address;
+ }
+ }
+ list device-vteps {
+ key "node-id ip-address";
+ leaf topology-id {
+ type string;
+ }
+ leaf node-id {
+ type string;
+ }
+ leaf ip-address {
+ type inet:ip-address;
+ }
+ }
+
+ }
+ }
+ }
+ identity itm {
+ base "config:service-type";
+ config:java-class "org.opendaylight.vpnservice.itm.api.IITMProvider";
+ }
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>itm-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <xtend.version>2.4.3</xtend.version>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>itm-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>interfacemgr-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>mdsalutil-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-interfaces</artifactId>
+ </dependency>
+ <!-- Testing Dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.console</artifactId>
+ <version>${karaf.shell.console.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>18.0</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-net</groupId>
+ <artifactId>commons-net</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>idmanager-api</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>idmanager-api</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Import-Package>
+ org.apache.felix.service.command,
+ org.apache.felix.gogo.commands,
+ org.apache.karaf.shell.console,
+ *
+ </Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. 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:vpnservice:itm?module=itm&revision=2015-07-01</capability>
+ <capability>urn:opendaylight:vpnservice:itm:impl?module=itm-impl&revision=2014-12-10</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: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:vpnservice:itm:impl">prefix:itm</type>
+ <name>itm-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>
+ <odlinterface>
+ <type xmlns:odlif="urn:opendaylight:vpnservice:interfacemgr">odlif:odl-interface</type>
+ <name>interfacemgr-service</name>
+ </odlinterface>
+ <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>
+ <notification-publish-service>
+ <type xmlns:bindingimpl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">bindingimpl:binding-new-notification-publish-service</type>
+ <name>binding-notification-publish-adapter</name>
+ </notification-publish-service>
+ <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:vpnservice:itm">prefix:itm</type>
+ <instance>
+ <name>itm</name>
+ <provider>/modules/module[type='itm'][name='itm-default']</provider>
+ </instance>
+ </service>
+ </services>
+ </data>
+ </configuration>
+</snapshot>
--- /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.itm.cli;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * The Utility class for ITM CLI.
+ */
+public final class ItmCliUtils {
+
+ /**
+ * Construct dpn id list.
+ *
+ * @param dpnIds
+ * the dpn ids
+ * @return the list
+ */
+ public static List<BigInteger> constructDpnIdList(final String dpnIds) {
+ final List<BigInteger> lstDpnIds = new ArrayList<>();
+ if (StringUtils.isNotBlank(dpnIds)) {
+ final String[] arrDpnIds = StringUtils.split(dpnIds, ',');
+ for (String dpn : arrDpnIds) {
+ if (StringUtils.isNumeric(StringUtils.trim(dpn))) {
+ lstDpnIds.add(new BigInteger(StringUtils.trim(dpn)));
+ } else {
+ Preconditions.checkArgument(false, String.format("DPN ID [%s] is not a numeric value.", dpn));
+ }
+ }
+ }
+ return lstDpnIds;
+ }
+}
--- /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.itm.cli;
+
+import java.util.Map;
+
+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.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.SubnetsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.SubnetsKey;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+public class SubnetObject {
+ private IpAddress _gatewayIp;
+ private SubnetsKey _key;
+ private IpPrefix _prefix;
+ private java.lang.Integer _vlanId;
+
+ public SubnetObject(IpAddress gWIP, SubnetsKey key, IpPrefix mask, Integer vlanId) {
+ _gatewayIp = gWIP;
+ _key = key;
+ _prefix = mask;
+ try {
+ if (vlanId != null) {
+ checkVlanIdRange(vlanId);
+ }
+ } catch (IllegalArgumentException e) {
+ System.out.println("Invalid VlanID. expected: 0 to 4095");
+ }
+ _vlanId = vlanId;
+ }
+
+ public IpAddress get_gatewayIp() {
+ return _gatewayIp;
+ }
+
+ public SubnetsKey get_key() {
+ return _key;
+ }
+
+ public IpPrefix get_prefix() {
+ return _prefix;
+ }
+
+ public java.lang.Integer get_vlanId() {
+ return _vlanId;
+ }
+
+ private int hash = 0;
+ private volatile boolean hashValid = false;
+
+ @Override
+ public int hashCode() {
+ if (hashValid) {
+ return hash;
+ }
+
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((_gatewayIp == null) ? 0 : _gatewayIp.hashCode());
+ result = prime * result + ((_key == null) ? 0 : _key.hashCode());
+ result = prime * result + ((_prefix == null) ? 0 : _prefix.hashCode());
+ result = prime * result + ((_vlanId == null) ? 0 : _vlanId.hashCode());
+ hash = result;
+ hashValid = true;
+ return result;
+ }
+
+ @Override
+ public boolean equals(java.lang.Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof SubnetObject)) {
+ return false;
+ }
+ SubnetObject other = (SubnetObject) obj;
+ if (_gatewayIp == null) {
+ if (other.get_gatewayIp() != null) {
+ return false;
+ }
+ } else if (!_gatewayIp.equals(other.get_gatewayIp())) {
+ return false;
+ }
+ if (_key == null) {
+ if (other.get_key() != null) {
+ return false;
+ }
+ } else if (!_key.equals(other.get_key())) {
+ return false;
+ }
+ if (_prefix == null) {
+ if (other.get_prefix() != null) {
+ return false;
+ }
+ } else if (!_prefix.equals(other.get_prefix())) {
+ return false;
+ }
+ if (_vlanId == null) {
+ if (other.get_vlanId() != null) {
+ return false;
+ }
+ } else if (!_vlanId.equals(other.get_vlanId())) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public java.lang.String toString() {
+ java.lang.StringBuilder builder = new java.lang.StringBuilder("Subnets [");
+ boolean first = true;
+
+ if (_gatewayIp != null) {
+ if (first) {
+ first = false;
+ } else {
+ builder.append(", ");
+ }
+ builder.append("_gatewayIp=");
+ builder.append(_gatewayIp);
+ }
+ if (_key != null) {
+ if (first) {
+ first = false;
+ } else {
+ builder.append(", ");
+ }
+ builder.append("_key=");
+ builder.append(_key);
+ }
+ if (_prefix != null) {
+ if (first) {
+ first = false;
+ } else {
+ builder.append(", ");
+ }
+ builder.append("_prefix=");
+ builder.append(_prefix);
+ }
+ if (_vlanId != null) {
+ if (first) {
+ first = false;
+ } else {
+ builder.append(", ");
+ }
+ builder.append("_vlanId=");
+ builder.append(_vlanId);
+ }
+ return builder.append(']').toString();
+ }
+
+ private static void checkVlanIdRange(final int value) {
+ if (value >= 0 && value <= 4095) {
+ return;
+ }
+ throw new IllegalArgumentException(String.format("Invalid range: %s, expected: [[0?4095]].", value));
+ }
+}
--- /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.itm.cli;
+
+import java.math.BigInteger;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.vpnservice.itm.api.IITMProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Command(scope = "tep", name = "add", description = "adding a tunnel end point")
+public class TepAdd extends OsgiCommandSupport {
+
+ @Argument(index = 0, name = "dpnId", description = "DPN-ID", required = false, multiValued = false)
+ private BigInteger dpnId;
+ @Argument(index = 1, name = "portNo", description = "port-name", required = false, multiValued = false)
+ private String portName;
+ @Argument(index = 2, name = "vlanId", description = "vlan-id", required = false, multiValued = false)
+ private Integer vlanId;
+ @Argument(index = 3, name = "ipAddress", description = "ip-address", required = false, multiValued = false)
+ private String ipAddress;
+ @Argument(index = 4, name = "subnetMask", description = "subnet-Mask", required = false, multiValued = false)
+ private String subnetMask;
+ @Argument(index = 5, name = "gatewayIp", description = "gateway-ip", required = false, multiValued = false)
+ private String gatewayIp;
+ @Argument(index = 6, name = "transportZone", description = "transport_zone", required = false, multiValued = false)
+ private String transportZone;
+ private static final Logger LOG = LoggerFactory.getLogger(TepAdd.class);
+ private IITMProvider itmProvider;
+
+ public void setItmProvider(IITMProvider itmProvider) {
+ this.itmProvider = itmProvider;
+ }
+
+ @Override
+ protected Object doExecute() {
+ try {
+ if (dpnId == null || portName == null || vlanId == null || ipAddress == null || subnetMask == null
+ || transportZone == null) {
+ System.out.println("Insufficient Arguments");
+ System.out.println("Correct Usage : exec tep-add dpnId portName vlanId ipAddress subnetMask gatewayIp transportZone");
+ return null;
+ }
+ LOG.debug("Executing create TEP command" + "\t" + dpnId + "\t" + portName + "\t" + vlanId + "\t"
+ + ipAddress + "\t" + subnetMask + "\t" + gatewayIp + "\t" + transportZone);
+ itmProvider.createLocalCache(dpnId, portName, vlanId, ipAddress, subnetMask, gatewayIp, transportZone);
+ } catch (IllegalArgumentException e) {
+ System.out.println(e.getMessage());
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ LOG.error("Exception occurred during execution of command \"tep-add\": ", e);
+ }
+ 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.itm.cli;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.net.util.SubnetUtils;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.interfacemgr.exceptions.InterfaceNotFoundException;
+import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
+//import org.opendaylight.vpnservice.interfacemgr.util.OperationalIfmUtil;
+import org.opendaylight.vpnservice.itm.globals.ITMConstants;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
+import org.opendaylight.vpnservice.itm.impl.ItmUtils;
+import org.opendaylight.vpnservice.mdsalutil.MDSALDataStoreUtils;
+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.inet.types.rev100924.IpPrefix;
+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.state.Interface.AdminStatus;
+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.vpnservice.itm.config.rev151102.TunnelMonitorEnabled;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.TunnelMonitorEnabledBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.TunnelMonitorInterval;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.TunnelMonitorIntervalBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList ;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnelKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZonesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZone;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZoneBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZoneKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.SubnetsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.SubnetsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.Vteps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.VtepsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.VtepsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+
+public class TepCommandHelper {
+
+ private static final Logger LOG = LoggerFactory.getLogger(TepCommandHelper.class);
+ private DataBroker dataBroker;
+ static int check = 0;
+ static short flag = 0;
+ /*
+ * boolean flag add_or_delete --- can be set to true if the last called tep
+ * command is Tep-add else set to false when Tep-delete is called
+ * tepCommandHelper object is created only once in session initiated
+ */
+ final Map<String, Map<SubnetObject, List<Vteps>>> tZones = new HashMap<String, Map<SubnetObject, List<Vteps>>>();
+ private List<Subnets> subnetList = new ArrayList<Subnets>();
+ private List<TransportZone> tZoneList = new ArrayList<TransportZone>();
+ private List<Vteps> vtepDelCommitList = new ArrayList<Vteps>();
+ private IInterfaceManager interfaceManager;
+
+ // private List<InstanceIdentifier<? extends DataObject>> vtepPaths = new
+ // ArrayList<>();
+
+
+ public TepCommandHelper(final DataBroker broker) {
+ this.dataBroker = broker;
+ }
+
+
+ public void setInterfaceManager(IInterfaceManager interfaceManager) {
+ this.interfaceManager = interfaceManager;
+ }
+
+ public void createLocalCache(BigInteger dpnId, String portName, Integer vlanId, String ipAddress,
+ String subnetMask, String gatewayIp, String transportZone) {
+
+ check++;
+ IpAddress ipAddressObj = null;
+ IpAddress gatewayIpObj = null;
+ IpPrefix subnetMaskObj = null;
+ VtepsKey vtepkey = new VtepsKey(dpnId, portName);
+ try {
+ ipAddressObj = new IpAddress(ipAddress.toCharArray());
+ gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
+ if (gatewayIp != null) {
+ gatewayIpObj = new IpAddress(gatewayIp.toCharArray());
+ } else {
+ LOG.debug("gateway is null");
+ }
+ } catch (Exception e) {
+ System.out.println("Invalid IpAddress. Expected: 1.0.0.0 to 254.255.255.255");
+ return;
+ }
+ try {
+ subnetMaskObj = new IpPrefix(subnetMask.toCharArray());
+ } catch (Exception e) {
+ System.out.println("Invalid Subnet Mask. Expected: 0.0.0.0/0 to 255.255.255.255/32");
+ return;
+ }
+
+ if (!validateIPs(ipAddress, subnetMask, gatewayIp)) {
+ System.out.println("IpAddress and gateWayIp should belong to the subnet provided");
+ return;
+ }
+
+ if (checkTepPerTzPerDpn(transportZone, dpnId)) {
+ System.out.println("Only one end point per transport Zone per Dpn is allowed");
+ return;
+ }
+ Vteps vtepCli = new VtepsBuilder().setDpnId(dpnId).setIpAddress(ipAddressObj).setKey(vtepkey)
+ .setPortname(portName).build();
+ validateForDuplicates(vtepCli, transportZone);
+
+ SubnetsKey subnetsKey = new SubnetsKey(subnetMaskObj);
+ SubnetObject subObCli = new SubnetObject(gatewayIpObj, subnetsKey, subnetMaskObj, vlanId);
+ if (tZones.containsKey(transportZone)) {
+ Map<SubnetObject, List<Vteps>> subVtepMapTemp = (Map<SubnetObject, List<Vteps>>) tZones.get(transportZone);
+ if (subVtepMapTemp.containsKey(subObCli)) { // if Subnet exists
+ List<Vteps> vtepListTemp = (List<Vteps>) subVtepMapTemp.get(subObCli);
+ if (vtepListTemp.contains(vtepCli)) {
+ // do nothing
+ } else {
+ vtepListTemp.add(vtepCli);
+ }
+ } else { // subnet doesnt exist
+ if (checkExistingSubnet(subVtepMapTemp, subObCli)) {
+ System.out.println("subnet with subnet mask " + subObCli.get_key() + "already exists");
+ return;
+ }
+ List<Vteps> vtepListTemp = new ArrayList<Vteps>();
+ vtepListTemp.add(vtepCli);
+ subVtepMapTemp.put(subObCli, vtepListTemp);
+ }
+ } else {
+ List<Vteps> vtepListTemp = new ArrayList<Vteps>();
+ vtepListTemp.add(vtepCli);
+ Map<SubnetObject, List<Vteps>> subVtepMapTemp = new HashMap<SubnetObject, List<Vteps>>();
+ subVtepMapTemp.put(subObCli, vtepListTemp);
+ tZones.put(transportZone, subVtepMapTemp);
+ }
+ }
+
+ private boolean validateIPs(String ipAddress, String subnetMask, String gatewayIp) {
+ SubnetUtils utils = new SubnetUtils(subnetMask);
+ if ((utils.getInfo().isInRange(ipAddress)) && ((gatewayIp == null) || (utils.getInfo().isInRange(gatewayIp)))) {
+ return true;
+ } else {
+ LOG.trace("InValid IP");
+ return false;
+ }
+ }
+
+ /**
+ * Validate for duplicates.
+ *
+ * @param inputVtep
+ * the input vtep
+ * @param transportZone
+ * the transport zone
+ */
+ public void validateForDuplicates(Vteps inputVtep, String transportZone) {
+ Map<String, TransportZone> tZoneMap = getAllTransportZonesAsMap();
+
+ boolean isConfiguredTepGreType = isGreTunnelType(transportZone, tZoneMap);
+ // Checking for duplicates in local cache
+ for (String tZ : tZones.keySet()) {
+ boolean isGreType = isGreTunnelType(tZ, tZoneMap);
+ Map<SubnetObject, List<Vteps>> subVtepMapTemp = (Map<SubnetObject, List<Vteps>>) tZones.get(tZ);
+ for (SubnetObject subOb : subVtepMapTemp.keySet()) {
+ List<Vteps> vtepList = subVtepMapTemp.get(subOb);
+ validateForDuplicateAndSingleGreTep(inputVtep, isConfiguredTepGreType, isGreType, vtepList);
+ }
+ }
+ // Checking for duplicates in config DS
+ for (TransportZone tZ : tZoneMap.values()) {
+ boolean isGreType = false;
+ if (tZ.getTunnelType().equals(TunnelTypeGre.class)) {
+ isGreType = true;
+ }
+ for (Subnets sub : ItmUtils.emptyIfNull(tZ.getSubnets())) {
+ List<Vteps> vtepList = sub.getVteps();
+ validateForDuplicateAndSingleGreTep(inputVtep, isConfiguredTepGreType, isGreType, vtepList);
+ }
+ }
+ }
+
+ private void validateForDuplicateAndSingleGreTep(Vteps inputVtep, boolean isConfiguredTepGreType, boolean isGreType,
+ List<Vteps> vtepList) {
+ if (ItmUtils.isEmpty(vtepList)) {
+ return;
+ }
+ if (vtepList.contains(inputVtep)) {
+ Preconditions.checkArgument(false, "VTEP already exists");
+ }
+ BigInteger dpnId = inputVtep.getDpnId();
+ if (isConfiguredTepGreType && isGreType) {
+ for (Vteps vtep : vtepList) {
+ if (vtep.getDpnId().equals(dpnId)) {
+ String errMsg = new StringBuilder("DPN [").append(dpnId)
+ .append("] already configured with GRE TEP. Mutiple GRE TEP's on a single DPN are not allowed.")
+ .toString();
+ Preconditions.checkArgument(false, errMsg);
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets all transport zones as map.
+ *
+ * @return all transport zones as map
+ */
+ private Map<String, TransportZone> getAllTransportZonesAsMap() {
+ TransportZones tZones = getAllTransportZones();
+ Map<String, TransportZone> tZoneMap = new HashMap<>();
+ if( null != tZones) {
+ for (TransportZone tzone : ItmUtils.emptyIfNull(tZones.getTransportZone())) {
+ tZoneMap.put(tzone.getZoneName(), tzone);
+ }
+ }
+ return tZoneMap;
+ }
+
+ /**
+ * Checks if is gre tunnel type.
+ *
+ * @param tZoneName
+ * the zone name
+ * @param tZoneMap
+ * the zone map
+ * @return true, if is gre tunnel type
+ */
+ private boolean isGreTunnelType(String tZoneName, Map<String, TransportZone> tZoneMap) {
+ TransportZone tzone = tZoneMap.get(tZoneName);
+ /*
+ if (tzone != null && StringUtils.equalsIgnoreCase(ITMConstants.TUNNEL_TYPE_GRE, tzone.getTunnelType())) {
+ return true;
+ }
+ */
+ if( (tzone != null) && (tzone.getTunnelType()).equals(TunnelTypeGre.class) ) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Gets the transport zone.
+ *
+ * @param tzone
+ * the tzone
+ * @return the transport zone
+ */
+ public TransportZone getTransportZone(String tzone) {
+ InstanceIdentifier<TransportZone> tzonePath = InstanceIdentifier.builder(TransportZones.class)
+ .child(TransportZone.class, new TransportZoneKey(tzone)).build();
+ Optional<TransportZone> tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath,
+ dataBroker);
+ if (tZoneOptional.isPresent()) {
+ return tZoneOptional.get();
+ }
+ return null;
+ }
+
+ /**
+ * Gets the transport zone from config ds.
+ *
+ * @param tzone
+ * the tzone
+ * @return the transport zone
+ */
+ public TransportZone getTransportZoneFromConfigDS(String tzone) {
+ InstanceIdentifier<TransportZone> tzonePath = InstanceIdentifier.builder(TransportZones.class)
+ .child(TransportZone.class, new TransportZoneKey(tzone)).build();
+ Optional<TransportZone> tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath,
+ dataBroker);
+ if (tZoneOptional.isPresent()) {
+ return tZoneOptional.get();
+ }
+ return null;
+ }
+
+ /**
+ * Gets all transport zones.
+ *
+ * @return all transport zones
+ */
+ public TransportZones getAllTransportZones() {
+ InstanceIdentifier<TransportZones> path = InstanceIdentifier.builder(TransportZones.class).build();
+ Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
+ if (tZonesOptional.isPresent()) {
+ return tZonesOptional.get();
+ }
+ return null;
+ }
+
+ public boolean checkExistingSubnet(Map<SubnetObject, List<Vteps>> subVtepMapTemp, SubnetObject subObCli) {
+ for (SubnetObject subOb : subVtepMapTemp.keySet()) {
+ if (subOb.get_key().equals(subObCli.get_key())) {
+ if (!(subOb.get_vlanId().equals(subObCli.get_vlanId())))
+ return true;
+ if (!(subOb.get_gatewayIp().equals(subObCli.get_gatewayIp())))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean checkTepPerTzPerDpn(String tzone, BigInteger dpnId) {
+ // check in local cache
+ if (tZones.containsKey(tzone)) {
+ Map<SubnetObject, List<Vteps>> subVtepMapTemp = (Map<SubnetObject, List<Vteps>>) tZones.get(tzone);
+ for (SubnetObject subOb : subVtepMapTemp.keySet()) {
+ List<Vteps> vtepList = subVtepMapTemp.get(subOb);
+ for (Vteps vtep : vtepList)
+ if (vtep.getDpnId().equals(dpnId))
+ return true;
+ }
+ }
+
+ // check in DS
+ InstanceIdentifier<TransportZone> tzonePath =
+ InstanceIdentifier.builder(TransportZones.class)
+ .child(TransportZone.class, new TransportZoneKey(tzone)).build();
+ Optional<TransportZone> tZoneOptional =
+ ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, dataBroker);
+ if (tZoneOptional.isPresent()) {
+ TransportZone tz = tZoneOptional.get();
+ if (tz.getSubnets() == null || tz.getSubnets().isEmpty())
+ return false;
+ for (Subnets sub : tz.getSubnets()) {
+ if (sub.getVteps() == null || sub.getVteps().isEmpty())
+ continue;
+ for (Vteps vtep : sub.getVteps()) {
+ if (vtep.getDpnId().equals(dpnId)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public void buildTeps() {
+ TransportZones tZonesBuilt = null;
+ TransportZone tZone = null;
+ try {
+ LOG.debug("no of teps added" + check);
+ if (tZones != null || !tZones.isEmpty()) {
+ tZoneList = new ArrayList<TransportZone>();
+ for (String tZ : tZones.keySet()) {
+ LOG.debug("tZones" + tZ);
+ subnetList = new ArrayList<Subnets>();
+ Map<SubnetObject, List<Vteps>> subVtepMapTemp = (Map<SubnetObject, List<Vteps>>) tZones.get(tZ);
+ for (SubnetObject subOb : subVtepMapTemp.keySet()) {
+ LOG.debug("subnets" + subOb.get_prefix());
+ List<Vteps> vtepList = subVtepMapTemp.get(subOb);
+ Subnets subnet =
+ new SubnetsBuilder().setGatewayIp(subOb.get_gatewayIp())
+ .setKey(subOb.get_key()).setPrefix(subOb.get_prefix())
+ .setVlanId(subOb.get_vlanId()).setVteps(vtepList).build();
+ subnetList.add(subnet);
+ LOG.debug("vteps" + vtepList);
+ }
+ InstanceIdentifier<TransportZone> tZonepath =
+ InstanceIdentifier.builder(TransportZones.class)
+ .child(TransportZone.class, new TransportZoneKey(tZ)).build();
+ Optional<TransportZone> tZoneOptional =
+ ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tZonepath, dataBroker);
+ LOG.debug("read container from DS");
+ if (tZoneOptional.isPresent()) {
+ TransportZone tzoneFromDs = tZoneOptional.get();
+ LOG.debug("read tzone container" + tzoneFromDs.toString());
+ if (tzoneFromDs.getTunnelType() == null
+ || (tzoneFromDs.getTunnelType()).equals(TunnelTypeVxlan.class)) {
+ tZone =
+ new TransportZoneBuilder().setKey(new TransportZoneKey(tZ))
+ .setTunnelType(TunnelTypeVxlan.class).setSubnets(subnetList)
+ .setZoneName(tZ).build();
+ } else if ((tzoneFromDs.getTunnelType()).equals(TunnelTypeGre.class)) {
+ tZone =
+ new TransportZoneBuilder().setKey(new TransportZoneKey(tZ))
+ .setTunnelType(TunnelTypeGre.class).setSubnets(subnetList)
+ .setZoneName(tZ).build();
+ }
+ } else {
+ tZone =
+ new TransportZoneBuilder().setKey(new TransportZoneKey(tZ))
+ .setTunnelType(TunnelTypeVxlan.class).setSubnets(subnetList).setZoneName(tZ)
+ .build();
+ }
+ LOG.debug("tzone object" + tZone);
+ tZoneList.add(tZone);
+ }
+ tZonesBuilt = new TransportZonesBuilder().setTransportZone(tZoneList).build();
+ InstanceIdentifier<TransportZones> path = InstanceIdentifier.builder(TransportZones.class).build();
+ LOG.debug("InstanceIdentifier" + path);
+ ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, path, tZonesBuilt, dataBroker,
+ ItmUtils.DEFAULT_CALLBACK);
+ LOG.debug("wrote to Config DS" + tZonesBuilt);
+ tZones.clear();
+ tZoneList.clear();
+ subnetList.clear();
+ LOG.debug("Everything cleared");
+ } else {
+ LOG.debug("NO vteps were configured");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void showTeps(boolean monitorEnabled, int monitorInterval) {
+ boolean flag = false;
+ InstanceIdentifier<TransportZones> path = InstanceIdentifier.builder(TransportZones.class).build();
+ Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
+ if (tZonesOptional.isPresent()) {
+ TransportZones tZones = tZonesOptional.get();
+ if(tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty())
+ {
+ System.out.println("No teps configured");
+ return;
+ }
+ List<String> result = new ArrayList<String>();
+ result.add(String.format("Tunnel Monitoring (for VXLAN tunnels): %s", (monitorEnabled ? "On" : "Off")));
+ result.add(String.format("Tunnel Monitoring Interval (for VXLAN tunnels): %d", monitorInterval));
+ result.add(System.lineSeparator());
+ result.add(String.format("%-16s %-16s %-16s %-12s %-12s %-12s %-16s %-12s", "TransportZone", "TunnelType", "SubnetMask",
+ "GatewayIP", "VlanID", "DpnID", "IPAddress", "PortName"));
+ result.add("------------------------------------------------------------------------------------------------------------------------------");
+ for (TransportZone tZ : tZones.getTransportZone()) {
+ if (tZ.getSubnets() == null || tZ.getSubnets().isEmpty()) {
+ LOG.error("Transport Zone " + tZ.getZoneName() + "has no subnets");
+ continue;
+ }
+ for (Subnets sub : tZ.getSubnets()) {
+ if (sub.getVteps() == null || sub.getVteps().isEmpty()) {
+ LOG.error("Transport Zone " + tZ.getZoneName() + "subnet " + sub.getPrefix() + "has no vteps");
+ continue;
+ }
+ for (Vteps vtep : sub.getVteps()) {
+ flag = true;
+ String strTunnelType ;
+ if( (tZ.getTunnelType()).equals(TunnelTypeGre.class) )
+ strTunnelType = ITMConstants.TUNNEL_TYPE_GRE ;
+ else
+ strTunnelType = ITMConstants.TUNNEL_TYPE_VXLAN ;
+ result.add(String.format("%-16s %-16s %-16s %-12s %-12s %-12s %-16s %-12s", tZ.getZoneName(), strTunnelType, sub
+ .getPrefix().getIpv4Prefix().getValue(), sub.getGatewayIp().getIpv4Address()
+ .getValue(), sub.getVlanId().toString(), vtep.getDpnId().toString(), vtep
+ .getIpAddress().getIpv4Address().getValue(), vtep.getPortname().toString()));
+ }
+ }
+ }
+ if (flag == true) {
+ for (String p : result) {
+ System.out.println(p);
+ }
+ } else
+ System.out.println("No teps to display");
+ } else
+ System.out.println("No teps configured");
+ }
+
+
+ public void deleteVtep(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask,
+ String gatewayIp, String transportZone) {
+
+ IpAddress ipAddressObj = null;
+ IpAddress gatewayIpObj = null;
+ IpPrefix subnetMaskObj = null;
+ VtepsKey vtepkey = new VtepsKey(dpnId, portName);
+ try {
+ ipAddressObj = new IpAddress(ipAddress.toCharArray());
+ gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
+ if (gatewayIp != null) {
+ gatewayIpObj = new IpAddress(gatewayIp.toCharArray());
+ } else {
+ LOG.debug("gateway is null");
+ }
+ } catch (Exception e) {
+ System.out.println("Invalid IpAddress. Expected: 1.0.0.0 to 254.255.255.255");
+ return;
+ }
+ try {
+ subnetMaskObj = new IpPrefix(subnetMask.toCharArray());
+ } catch (Exception e) {
+ System.out.println("Invalid Subnet Mask. Expected: 0.0.0.0/0 to 255.255.255.255/32");
+ return;
+ }
+
+ if (!validateIPs(ipAddress, subnetMask, gatewayIp)) {
+ System.out.println("IpAddress and gateWayIp should belong to the subnet provided");
+ return;
+ }
+ SubnetsKey subnetsKey = new SubnetsKey(subnetMaskObj);
+ Vteps vtepCli = null;
+ Subnets subCli = null;
+
+ InstanceIdentifier<Vteps> vpath =
+ InstanceIdentifier.builder(TransportZones.class)
+ .child(TransportZone.class, new TransportZoneKey(transportZone))
+ .child(Subnets.class, subnetsKey).child(Vteps.class, vtepkey).build();
+
+ // check if present in tzones and delete from cache
+ boolean existsInCache = isInCache(dpnId, portName, vlanId, ipAddress, subnetMask, gatewayIp, transportZone);
+ if (!existsInCache) {
+ Optional<Vteps> vtepOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, vpath, dataBroker);
+ if (vtepOptional.isPresent()) {
+ vtepCli = vtepOptional.get();
+ if(vtepCli.getIpAddress().equals(ipAddressObj)){
+ InstanceIdentifier<Subnets> spath =
+ InstanceIdentifier
+ .builder(TransportZones.class)
+ .child(TransportZone.class, new TransportZoneKey(transportZone))
+ .child(Subnets.class, subnetsKey).build();
+ Optional<Subnets> subOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, spath, dataBroker);
+ if (subOptional.isPresent()) {
+ subCli = subOptional.get();
+ if(subCli.getGatewayIp().equals(gatewayIpObj) && subCli.getVlanId().equals(vlanId)){
+ vtepDelCommitList.add(vtepCli);
+ }
+ else
+ System.out.println(String.format("vtep with this vlan or gateway doesnt exist"));
+ }
+ }
+ else
+ System.out.println(String.format("Vtep with this ipaddress doesnt exist"));
+ } else {
+ System.out.println(String.format("Vtep Doesnt exist"));
+ }
+ }
+ }
+
+ public <T extends DataObject> void deleteOnCommit() {
+ List<InstanceIdentifier<T>> vtepPaths = new ArrayList<>();
+ List<InstanceIdentifier<T>> subnetPaths = new ArrayList<>();
+ List<InstanceIdentifier<T>> tzPaths = new ArrayList<>();
+ List<Subnets> subDelList = new ArrayList<Subnets>();
+ List<TransportZone> tzDelList = new ArrayList<TransportZone>();
+ List<Vteps> vtepDelList = new ArrayList<Vteps>();
+ List<InstanceIdentifier<T>> allPaths = new ArrayList<>();
+ try {
+ if (vtepDelCommitList != null && !vtepDelCommitList.isEmpty()) {
+ InstanceIdentifier<TransportZones> path = InstanceIdentifier.builder(TransportZones.class).build();
+ Optional<TransportZones> tZonesOptional =
+ ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
+ if (tZonesOptional.isPresent()) {
+ TransportZones tZones = tZonesOptional.get();
+ for (TransportZone tZ : tZones.getTransportZone()) {
+ if (tZ.getSubnets() == null || tZ.getSubnets().isEmpty())
+ continue;
+ for (Subnets sub : tZ.getSubnets()) {
+ vtepDelList.addAll(vtepDelCommitList);
+ for (Vteps vtep : vtepDelList) {
+ InstanceIdentifier<T> vpath =
+ (InstanceIdentifier<T>) InstanceIdentifier
+ .builder(TransportZones.class)
+ .child(TransportZone.class, tZ.getKey())
+ .child(Subnets.class, sub.getKey())
+ .child(Vteps.class, vtep.getKey()).build();
+ if (sub.getVteps().remove(vtep)) {
+ vtepPaths.add(vpath);
+ if (sub.getVteps().size() == 0 || sub.getVteps() == null) {
+ subDelList.add(sub);
+ }
+
+ }
+ }
+ }
+ }
+
+ for (TransportZone tZ : tZones.getTransportZone()) {
+ if (tZ.getSubnets() == null || tZ.getSubnets().isEmpty())
+ continue;
+ for (Subnets sub : subDelList) {
+ if (tZ.getSubnets().remove(sub)) {
+ InstanceIdentifier<T> spath =
+ (InstanceIdentifier<T>) InstanceIdentifier
+ .builder(TransportZones.class)
+ .child(TransportZone.class, tZ.getKey())
+ .child(Subnets.class, sub.getKey()).build();
+ subnetPaths.add(spath);
+ if (tZ.getSubnets() == null || tZ.getSubnets().size() == 0) {
+ tzDelList.add(tZ);
+ }
+ }
+ }
+ }
+
+ for (TransportZone tZ : tzDelList) {
+ if (tZones.getTransportZone().remove(tZ)) {
+ InstanceIdentifier<T> tpath =
+ (InstanceIdentifier<T>) InstanceIdentifier.builder(TransportZones.class)
+ .child(TransportZone.class, tZ.getKey()).build();
+ tzPaths.add(tpath);
+ if (tZones.getTransportZone() == null || tZones.getTransportZone().size() == 0) {
+ MDSALDataStoreUtils.asyncRemove(dataBroker, LogicalDatastoreType.CONFIGURATION, path,
+ ItmUtils.DEFAULT_CALLBACK);
+ return;
+ }
+ }
+ }
+ allPaths.addAll(vtepPaths);
+ allPaths.addAll(subnetPaths);
+ allPaths.addAll(tzPaths);
+ ItmUtils.asyncBulkRemove(dataBroker, LogicalDatastoreType.CONFIGURATION, allPaths,
+ ItmUtils.DEFAULT_CALLBACK);
+ }
+ vtepPaths.clear();
+ subnetPaths.clear();
+ tzPaths.clear();
+ allPaths.clear();
+ vtepDelCommitList.clear();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void showState(TunnelList tunnels, boolean tunnelMonitorEnabled) {
+ IfTunnel tunnelInterface = null;
+ IfL2vlan l2Vlan = null;
+ List<InternalTunnel> tunnelLists = tunnels.getInternalTunnel();
+ if (tunnelLists == null || tunnelLists.isEmpty()) {
+ System.out.println("No Internal Tunnels Exist");
+ return;
+ }
+ if (!tunnelMonitorEnabled) {
+ System.out.println("Tunnel Monitoring is Off");
+ }
+ String displayFormat = "%-16s %-16s %-16s %-16s %-16s %-8s %-10s %-10s";
+ System.out.println(String.format(displayFormat, "Tunnel Name", "Source-DPN",
+ "Destination-DPN", "Source-IP", "Destination-IP", "Vlan Id", "Trunk-State", "Transport Type"));
+ System.out.println("-------------------------------------------------------------------------------------------------------------------------------------");
+
+ for (InternalTunnel tunnel : tunnelLists) {
+ String tunnelInterfaceName = tunnel.getTunnelInterfaceName();
+ LOG.trace("tunnelInterfaceName::: {}", tunnelInterfaceName);
+
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
+ ItmUtils.buildStateInterfaceId(tunnelInterfaceName);
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateOptional =
+ ItmUtils.read(LogicalDatastoreType.OPERATIONAL, ifStateId, dataBroker);
+ String tunnelState = "DOWN" ;
+ if (ifStateOptional.isPresent()) {
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface iface = ifStateOptional.get() ;
+ if(iface.getAdminStatus() == AdminStatus.Up && iface.getOperStatus() == OperStatus.Up)
+ tunnelState = "UP" ;
+ }
+ InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(tunnelInterfaceName);
+ Optional<Interface> ifaceObj = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, trunkIdentifier, dataBroker) ;
+ if (ifaceObj.isPresent()) {
+ l2Vlan = (IfL2vlan) ifaceObj.get().getAugmentation(IfL2vlan.class);
+ tunnelInterface = (IfTunnel) ifaceObj.get().getAugmentation(IfTunnel.class);
+ }
+
+ Class<? extends TunnelTypeBase> tunType = tunnelInterface.getTunnelInterfaceType();
+ String tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN;
+ if( tunType.equals(TunnelTypeVxlan.class))
+ tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN ;
+ else if( tunType.equals(TunnelTypeGre.class) )
+ tunnelType = ITMConstants.TUNNEL_TYPE_GRE ;
+ int vlanId = 0;
+ if( l2Vlan != null ) {
+ vlanId = l2Vlan.getVlanId().getValue() ;
+ }
+ System.out.println(String.format(displayFormat, tunnel.getTunnelInterfaceName(), tunnel
+ .getSourceDPN().toString(), tunnel.getDestinationDPN().toString(), tunnelInterface.getTunnelSource().getIpv4Address().getValue(), tunnelInterface.getTunnelDestination().getIpv4Address().getValue(),vlanId, tunnelState ,
+ tunnelType));
+ }
+ }
+
+ // deletes from ADD-cache if it exists.
+ public boolean isInCache(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask,
+ String gatewayIp, String transportZone) {
+ boolean exists = false;
+ VtepsKey vtepkey = new VtepsKey(dpnId, portName);
+ IpAddress ipAddressObj = new IpAddress(ipAddress.toCharArray());
+ IpPrefix subnetMaskObj = new IpPrefix(subnetMask.toCharArray());
+ IpAddress gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
+ if (gatewayIp != null) {
+ gatewayIpObj = new IpAddress(gatewayIp.toCharArray());
+ } else {
+ LOG.debug("gateway is null");
+ }
+ SubnetsKey subnetsKey = new SubnetsKey(subnetMaskObj);
+ Vteps vtepCli =
+ new VtepsBuilder().setDpnId(dpnId).setIpAddress(ipAddressObj).setKey(vtepkey)
+ .setPortname(portName).build();
+ SubnetObject subObCli = new SubnetObject(gatewayIpObj, subnetsKey, subnetMaskObj, vlanId);
+
+ if (tZones.containsKey(transportZone)) {
+ Map<SubnetObject, List<Vteps>> subVtepMapTemp = (Map<SubnetObject, List<Vteps>>) tZones.get(transportZone);
+ if (subVtepMapTemp.containsKey(subObCli)) { // if Subnet exists
+ List<Vteps> vtepListTemp = (List<Vteps>) subVtepMapTemp.get(subObCli);
+ if (vtepListTemp.contains(vtepCli)) {
+ exists = true; // return true if tzones has vtep
+ vtepListTemp.remove(vtepCli);
+ if (vtepListTemp.size() == 0) {
+ subVtepMapTemp.remove(subObCli);
+ if (subVtepMapTemp.size() == 0) {
+ tZones.remove(transportZone);
+ }
+ }
+ } else {
+ System.out.println("Vtep " + "has not been configured");
+ }
+ }
+ }
+ return exists;
+ }
+
+ public void configureTunnelType(String tZoneName, String tunnelType) {
+ LOG.debug("configureTunnelType {} for transportZone {}", tunnelType, tZoneName);
+
+ TransportZone tZoneFromConfigDS = getTransportZoneFromConfigDS(tZoneName);
+ validateTunnelType(tZoneName, tunnelType,tZoneFromConfigDS);
+
+ if (tZoneFromConfigDS != null) {
+ LOG.debug("Transport zone {} with tunnel type {} already exists. No action required.", tZoneName,
+ tunnelType);
+ return;
+ }
+ TransportZones transportZones = null;
+ List<TransportZone> tZoneList = null;
+ InstanceIdentifier<TransportZones> path = InstanceIdentifier.builder(TransportZones.class).build();
+ Optional<TransportZones> tZones = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
+ Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
+ if( tunnelType.equals(ITMConstants.TUNNEL_TYPE_VXLAN))
+ tunType = TunnelTypeVxlan.class ;
+ else if( tunnelType.equals(ITMConstants.TUNNEL_TYPE_GRE) )
+ tunType = TunnelTypeGre.class ;
+
+ TransportZone tZone = new TransportZoneBuilder().setKey(new TransportZoneKey(tZoneName))
+ .setTunnelType(tunType).build();
+ if (tZones.isPresent()) {
+ tZoneList = tZones.get().getTransportZone();
+ if(tZoneList == null || tZoneList.isEmpty()) {
+ tZoneList = new ArrayList<TransportZone>();
+ }
+ } else {
+ tZoneList = new ArrayList<TransportZone>();
+ }
+ tZoneList.add(tZone);
+ transportZones = new TransportZonesBuilder().setTransportZone(tZoneList).build();
+ ItmUtils.syncWrite(LogicalDatastoreType.CONFIGURATION, path, transportZones, dataBroker);
+
+ }
+
+ /**
+ * Validate tunnel type.
+ *
+ * @param tZoneName
+ * the t zone name
+ * @param tunnelType
+ * the tunnel type
+ */
+ private void validateTunnelType(String tZoneName, String tunnelType,TransportZone tZoneFromConfigDS) {
+ /*
+ String strTunnelType = ItmUtils.validateTunnelType(tunnelType);
+
+ TransportZone tZone = getTransportZone(tZoneName);
+ if (tZone != null) {
+ if (!StringUtils.equalsIgnoreCase(strTunnelType, tZone.getTunnelType())
+ && ItmUtils.isNotEmpty(tZone.getSubnets())) {
+ String errorMsg = new StringBuilder("Changing the tunnel type from ").append(tZone.getTunnelType())
+ .append(" to ").append(strTunnelType)
+ .append(" is not allowed for already configured transport zone [").append(tZoneName)
+ .append("].").toString();
+ Preconditions.checkArgument(false, errorMsg);
+ }
+ }
+ */
+ String strTunnelType = ItmUtils.validateTunnelType(tunnelType);
+ Class<? extends TunnelTypeBase> tunType ;
+ if( strTunnelType.equals(ITMConstants.TUNNEL_TYPE_VXLAN))
+ tunType = TunnelTypeVxlan.class ;
+ else
+ tunType = TunnelTypeGre.class ;
+ //TransportZone tZone = getTransportZone(tZoneName);
+ // if (tZone != null) {
+ if (tZoneFromConfigDS != null) {
+ if( (!tZoneFromConfigDS.getTunnelType().equals(tunType)) && ItmUtils.isNotEmpty(tZoneFromConfigDS.getSubnets())) {
+ String errorMsg = new StringBuilder("Changing the tunnel type from ").append(tZoneFromConfigDS.getTunnelType())
+ .append(" to ").append(strTunnelType)
+ .append(" is not allowed for already configured transport zone [").append(tZoneName)
+ .append("].").toString();
+ Preconditions.checkArgument(false, errorMsg);
+ }
+ }
+ }
+
+ public void configureTunnelMonitorEnabled(boolean monitorEnabled) {
+ InstanceIdentifier<TunnelMonitorEnabled> path = InstanceIdentifier.builder(TunnelMonitorEnabled.class).build();
+ Optional<TunnelMonitorEnabled> storedTunnelMonitor = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
+ if (!storedTunnelMonitor.isPresent() || storedTunnelMonitor.get().isEnabled() != monitorEnabled) {
+ TunnelMonitorEnabled tunnelMonitor = new TunnelMonitorEnabledBuilder().setEnabled(monitorEnabled).build();
+ ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, path, tunnelMonitor, dataBroker,
+ ItmUtils.DEFAULT_CALLBACK);
+ }
+ }
+
+ public void configureTunnelMonitorInterval(int interval) {
+ InstanceIdentifier<TunnelMonitorInterval> path = InstanceIdentifier.builder(TunnelMonitorInterval.class).build();
+ Optional<TunnelMonitorInterval> storedTunnelMonitor = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
+ if (!storedTunnelMonitor.isPresent() || storedTunnelMonitor.get().getInterval() != interval) {
+ TunnelMonitorInterval tunnelMonitor = new TunnelMonitorIntervalBuilder().setInterval(interval).build();
+ ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, path, tunnelMonitor, dataBroker,
+ ItmUtils.DEFAULT_CALLBACK);
+ }
+ }
+}
--- /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.itm.cli;
+
+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.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.itm.api.IITMProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+@Command(scope = "tep", name = "commit",
+ description = "commits the configuration so that actual tunnel-building happens")
+public class TepCommit extends OsgiCommandSupport {
+ private static final Logger logger = LoggerFactory.getLogger(TepCommit.class);
+
+ private IITMProvider itmProvider;
+
+ public void setItmProvider(IITMProvider itmProvider) {
+ this.itmProvider = itmProvider;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+
+ try {
+ itmProvider.commitTeps();
+ logger.debug("Executing commit TEP command");
+ } catch (NullPointerException 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.itm.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.vpnservice.itm.api.IITMProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+@Command(scope = "tep", name = "configure-tunnelType",
+ description = "configuring the tunnel type for a transport zone")
+public class TepConfigureTunnelType extends OsgiCommandSupport {
+
+ @Argument(index = 0, name = "TransportZoneName", description = "TransportZoneName", required = true, multiValued = false)
+ private String tZoneName;
+ @Argument(index = 1, name = "TunnelType", description = "Tunnel-Type", required = true, multiValued = false)
+ private String tunnelType;
+
+
+ private static final Logger LOG = LoggerFactory.getLogger(TepConfigureTunnelType.class);
+
+ private IITMProvider itmProvider;
+
+ public void setItmProvider(IITMProvider itmProvider) {
+ this.itmProvider = itmProvider;
+ }
+
+ @Override
+ protected Object doExecute() {
+ try {
+ LOG.debug("TepConfigureTunnelType: configureTunnelType {} for transportZone {}", tunnelType, tZoneName);
+ itmProvider.configureTunnelType(tZoneName, tunnelType);
+ } catch (IllegalArgumentException e) {
+ System.out.println(e.getMessage());
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ LOG.error("Exception occurred during execution of command \"tep:configure-tunnelType\": ", e);
+ }
+ 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.itm.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.opendaylight.vpnservice.itm.api.IITMProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Command(scope = "tep", name = "delete", description = "deleting a tunnel end point")
+public class TepDelete extends OsgiCommandSupport {
+
+ @Argument(index = 0, name = "dpnId", description = "DPN-ID", required = false, multiValued = false)
+ private BigInteger dpnId;
+ @Argument(index = 1, name = "portName", description = "port-number", required = false, multiValued = false)
+ private String portName;
+ @Argument(index = 2, name = "vlanId", description = "vlan-id", required = false, multiValued = false)
+ private Integer vlanId;
+ @Argument(index = 3, name = "ipAddress", description = "ip-address", required = false, multiValued = false)
+ private String ipAddress;
+ @Argument(index = 4, name = "subnetMask", description = "subnet-Mask", required = false, multiValued = false)
+ private String subnetMask;
+ @Argument(index = 5, name = "gatewayIp", description = "gateway-ip", required = false, multiValued = false)
+ private String gatewayIp;
+ @Argument(index = 6, name = "transportZone", description = "transport_zone", required = false, multiValued = false)
+ private String transportZone;
+
+ private static final Logger logger = LoggerFactory.getLogger(TepDelete.class);
+ private IITMProvider itmProvider;
+
+ public void setItmProvider(IITMProvider itmProvider) {
+ this.itmProvider = itmProvider;
+ }
+ @Override
+ protected Object doExecute() throws Exception {
+
+ if (dpnId == null || portName == null || vlanId == null || ipAddress == null || subnetMask == null
+ || transportZone == null) {
+ System.out.println("Insufficient Arguments");
+ System.out.println("Correct Usage : exec tep-delete dpnId portName vlanId ipAddress subnetMask gatewayIp transportZone");
+ return null;
+ }
+ itmProvider.deleteVtep(dpnId, portName, vlanId, ipAddress, subnetMask, gatewayIp, transportZone);
+ logger.trace("Executing delete TEP command");
+
+ 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.itm.cli;
+
+import java.util.ArrayList;
+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 com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.FutureCallback;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+//import org.opendaylight.vpnservice.interfacemgr.util.ConfigIfmUtil;
+import org.opendaylight.vpnservice.itm.api.IITMProvider;
+import org.opendaylight.vpnservice.itm.impl.ItmUtils;
+import org.opendaylight.vpnservice.mdsalutil.MDSALDataStoreUtils;
+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.inventory.rev130819.Nodes;
+//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.op.rev150701.Tunnels;
+//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.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+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.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+
+@Command(scope = "tep", name = "deleteDatastore", description = "view the configured tunnel endpoints")
+public class TepDeleteDatastore <T extends DataObject> extends OsgiCommandSupport {
+ private static final Logger logger = LoggerFactory.getLogger(TepDeleteDatastore.class);
+ private IITMProvider itmProvider;
+
+ public void setItmProvider(IITMProvider itmProvider) {
+ this.itmProvider = itmProvider;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ DataBroker dataBroker = itmProvider.getDataBroker();
+ InstanceIdentifier < TransportZones > itmConfigPath = InstanceIdentifier.builder(TransportZones.class).build();
+ // InstanceIdentifier<Tunnels> tunnelsConfigPath = InstanceIdentifier.builder(Tunnels.class).build();
+ InstanceIdentifier<Interfaces> InterfacesConfigPath = InstanceIdentifier.builder(Interfaces.class).build();
+ // InstanceIdentifier<TunnelsState> tnStateOpPath = InstanceIdentifier.builder(TunnelsState.class).build();
+ InstanceIdentifier<InterfacesState> ifStateOpPath = InstanceIdentifier.builder(InterfacesState.class).build();
+ InstanceIdentifier<Nodes> frmConfigPath = InstanceIdentifier.builder(Nodes.class).build();
+ List<InstanceIdentifier<T>> allConfigPaths =
+ new ArrayList<>();
+ allConfigPaths.add((InstanceIdentifier<T>) itmConfigPath);
+ allConfigPaths.add((InstanceIdentifier<T>) InterfacesConfigPath);
+ allConfigPaths.add((InstanceIdentifier<T>) frmConfigPath);
+ //allConfigPaths.add((InstanceIdentifier<T>) tunnelsConfigPath);
+ ItmUtils.asyncBulkRemove(dataBroker, LogicalDatastoreType.CONFIGURATION,allConfigPaths,
+ ItmUtils.DEFAULT_CALLBACK);
+ List<InstanceIdentifier<T>> allOperationalPaths =
+ new ArrayList<>();
+ // allOperationalPaths.add((InstanceIdentifier<T>) tnStateOpPath);
+ allOperationalPaths.add((InstanceIdentifier<T>) ifStateOpPath);
+ ItmUtils.asyncBulkRemove(dataBroker, LogicalDatastoreType.OPERATIONAL, allOperationalPaths,
+ ItmUtils.DEFAULT_CALLBACK);
+
+ 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.itm.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.vpnservice.itm.api.IITMProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Command(scope = "tep", name = "enable-tunnel-monitor", description = "switch ON/OFF supervision of VxLAN tunnels")
+public class TepEnableTunnelMonitor extends OsgiCommandSupport {
+
+ private static final Logger logger = LoggerFactory.getLogger(TepEnableTunnelMonitor.class);
+
+ @Argument(index = 0, name = "true|false", description = "true|false to enable/disable Tunnel Monitoring", required = true, multiValued = false)
+ private Boolean enableTunnelMonitor;
+
+ private IITMProvider itmProvider;
+
+ public void setItmProvider(IITMProvider itmProvider) {
+ this.itmProvider = itmProvider;
+ }
+
+ @Override
+ protected Object doExecute() {
+ try {
+ logger.debug("Executing Enable Tunnel Monitor command");
+ itmProvider.configureTunnelMonitorEnabled(enableTunnelMonitor);
+ } catch (NullPointerException 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.itm.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.vpnservice.itm.api.IITMProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Command(scope = "tep", name = "monitor-interval", description = "configuring tunnel monitoring time interval")
+public class TepMonitor extends OsgiCommandSupport {
+
+ @Argument(index = 0, name = "interval", description = "monitoring interval", required = true,
+ multiValued = false)
+ private Integer interval;
+
+ private static final Logger logger = LoggerFactory.getLogger(TepMonitor.class);
+ private IITMProvider itmProvider;
+
+ public void setItmProvider(IITMProvider itmProvider) {
+ this.itmProvider = itmProvider;
+ }
+
+ @Override
+ protected Object doExecute() {
+ try {
+ logger.debug("Executing TEP monitor command with interval: " + "\t" + interval);
+ if(!(interval >= 5 && interval <=30)){
+ System.out.println("Monitoring Interval must be in the range 5 - 30");
+ }
+ else {
+ itmProvider.configureTunnelMonitorInterval(interval);
+ }
+ } 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.itm.cli;
+
+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 com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.FutureCallback;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.itm.api.IITMProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+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.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+
+@Command(scope = "tep", name = "show", description = "view the configured tunnel endpoints")
+public class TepShow extends OsgiCommandSupport {
+ private static final Logger logger = LoggerFactory.getLogger(TepShow.class);
+ private IITMProvider itmProvider;
+
+ public void setItmProvider(IITMProvider itmProvider) {
+ this.itmProvider = itmProvider;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ logger.debug("Executing show TEP command");
+ itmProvider.showTeps();
+ 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.itm.cli;
+
+import com.google.common.base.Optional;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.itm.api.IITMProvider;
+import org.opendaylight.vpnservice.itm.impl.ItmUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList ;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Command(scope = "tep", name = "show-state", description="Monitors tunnel state")
+
+ public class TepShowState extends OsgiCommandSupport {
+
+ private IITMProvider itmProvider;
+
+ public void setItmProvider(IITMProvider itmProvider) {
+ this.itmProvider = itmProvider;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+
+ DataBroker broker = itmProvider.getDataBroker();
+ List<String> result = new ArrayList<String>();
+ InstanceIdentifier<TunnelList> path = InstanceIdentifier.builder(TunnelList.class).build();
+ Optional<TunnelList> tunnels = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, broker);
+ if (tunnels.isPresent()) {
+ itmProvider.showState(tunnels.get());
+ }
+ else
+ System.out.println("No Internal Tunnels Exist");
+ 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.itm.cli;
+
+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;
+
+@Command(scope = "tep", name = "state-show", description="Monitors tunnel state")
+
+ public class TepStateShow extends OsgiCommandSupport {
+
+ @Override
+
+ protected Object doExecute() throws Exception {
+
+ System.out.println("Executing show TEP states command");
+
+ 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.itm.cli;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.vpnservice.itm.api.IITMProvider;
+import org.opendaylight.vpnservice.itm.globals.ITMConstants;
+import org.opendaylight.vpnservice.itm.impl.ItmUtils;
+import org.opendaylight.vpnservice.itm.cli.ItmCliUtils;
+//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.rev151102.vtep.config.schemas.VtepConfigSchema;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.VtepConfigSchema;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The Class which implements karaf command "vtep:schema-add".
+ */
+@Command(scope = "vtep", name = "schema-add", description = "Adding a VTEP schema.")
+public class VtepSchemaAdd extends OsgiCommandSupport {
+
+ private static final String SCHEMA_NAME = "--schema-name";
+ private static final String PORT_NAME = "--port-name";
+ private static final String VLAN_ID = "--vlan-id";
+ private static final String SUBNET_CIDR = "--subnet-cidr";
+ private static final String TRANSPORT_ZONE = "--transport-zone";
+ private static final String DPN_IDS = "--dpn-ids";
+ private static final String GATEWAY_IP = "--gateway-ip";
+ private static final String TUNNEL_TYPE = "--tunnel-type";
+ private static final String EXCLUDE_IP_FILTER = "--exclude-ip-filter";
+
+ /** The schema name. */
+ @Option(name = SCHEMA_NAME, aliases = { "-s" }, description = "Schema name", required = true, multiValued = false)
+ private String schemaName;
+
+ /** The port name. */
+ @Option(name = PORT_NAME, aliases = { "-p" }, description = "Port name", required = true, multiValued = false)
+ private String portName;
+
+ /** The vlan id. */
+ @Option(name = VLAN_ID, aliases = { "-v" }, description = "VLAN ID", required = true, multiValued = false)
+ private Integer vlanId;
+
+ /** The subnet mask. */
+ @Option(name = SUBNET_CIDR, aliases = {
+ "-sc" }, description = "Subnet Mask in CIDR-notation string, e.g. 10.0.0.0/24", required = true, multiValued = false)
+ private String subnetCIDR;
+
+ /** The transport zone. */
+ @Option(name = TRANSPORT_ZONE, aliases = {
+ "-tz" }, description = "Transport zone", required = true, multiValued = false)
+ private String transportZone;
+
+ /** The dpn ids. */
+ @Option(name = DPN_IDS, aliases = {
+ "-d" }, description = "DPN ID's in comma separated values. e.g: 2,3,10", required = false, multiValued = false)
+ private String dpnIds;
+
+ /** The gateway ip. */
+ @Option(name = GATEWAY_IP, aliases = {
+ "-g" }, description = "Gateway IP address", required = false, multiValued = false)
+ private String gatewayIp;
+
+ /** The tunnel type. */
+ @Option(name = TUNNEL_TYPE, aliases = {
+ "-t" }, description = "Tunnel type. Value: VXLAN | GRE. Default: VXLAN", required = false, multiValued = false)
+ private String tunnelType;
+
+ /** The exclude ip filter. */
+ @Option(name = EXCLUDE_IP_FILTER, aliases = {
+ "-ex" }, description = "IP Addresses which needs to be excluded from the specified subnet. IP address range or comma separated IP addresses can to be specified. e.g: 10.0.0.1-10.0.0.20,10.0.0.30,10.0.0.35", required = false, multiValued = false)
+ private String excludeIpFilter;
+
+ /** The Constant logger. */
+ private static final Logger LOG = LoggerFactory.getLogger(VtepSchemaAdd.class);
+
+ /** The itm provider. */
+ private IITMProvider itmProvider;
+
+ /**
+ * Sets the itm provider.
+ *
+ * @param itmProvider
+ * the new itm provider
+ */
+ public void setItmProvider(IITMProvider itmProvider) {
+ this.itmProvider = itmProvider;
+ }
+
+ /**
+ * Command Usage.
+ */
+ private void usage() {
+ System.out.println(String.format(
+ "usage: vtep:schema-add [%s schema-name] [%s port-name] [%s vlan-id] [%s subnet-cidr] [%s transport-zone] [%s dpn-ids] [%s gateway-ip] [%s tunnel-type] [%s exclude-ip-filter]",
+ SCHEMA_NAME, PORT_NAME, VLAN_ID, SUBNET_CIDR, TRANSPORT_ZONE, DPN_IDS, GATEWAY_IP, TUNNEL_TYPE,
+ EXCLUDE_IP_FILTER));
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.karaf.shell.console.AbstractAction#doExecute()
+ */
+ @Override
+ protected Object doExecute() {
+ try {
+ if (this.schemaName == null || this.portName == null || this.vlanId == null || this.subnetCIDR == null
+ || this.transportZone == null) {
+ usage();
+ return null;
+ }
+ LOG.debug("Executing vtep:schema-add command\t {} \t {} \t {} \t {} \t {} \t {} \t {} \t {} \t {}", schemaName,
+ portName, vlanId, subnetCIDR, gatewayIp, transportZone, tunnelType, dpnIds, excludeIpFilter);
+
+ if( null == tunnelType) {
+ tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN ;
+ }
+ VtepConfigSchema schema = ItmUtils.constructVtepConfigSchema(schemaName, portName, vlanId, subnetCIDR,
+ gatewayIp, transportZone, tunnelType, ItmCliUtils.constructDpnIdList(dpnIds), excludeIpFilter);
+ this.itmProvider.addVtepConfigSchema(schema);
+
+ } catch (IllegalArgumentException e) {
+ System.out.println(e.getMessage());
+ } catch (Exception e) {
+ LOG.error("Exception occurred during execution of command \"vtep:schema-add\": ", e);
+ }
+ 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.itm.cli;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.vpnservice.itm.api.IITMProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The Class which implements karaf command "vtep:schema-delete".
+ */
+@Command(scope = "vtep", name = "schema-delete", description = "Delete VTEP schema.")
+public class VtepSchemaDelete extends OsgiCommandSupport {
+
+ private static final String ALL = "all";
+
+ @Argument(index = 0, name = ALL, description = "Delete all VTEP schemas", required = true, multiValued = false)
+ String deleteAll = null;
+
+ /** The Constant logger. */
+ private static final Logger LOG = LoggerFactory.getLogger(VtepSchemaDelete.class);
+
+ /** The itm provider. */
+ private IITMProvider itmProvider;
+
+ /**
+ * Sets the itm provider.
+ *
+ * @param itmProvider
+ * the new itm provider
+ */
+ public void setItmProvider(IITMProvider itmProvider) {
+ this.itmProvider = itmProvider;
+ }
+
+ private void usage() {
+ System.out.println("usage: vtep:schema-delete all");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.karaf.shell.console.AbstractAction#doExecute()
+ */
+ @Override
+ protected Object doExecute() {
+ try {
+ if (this.deleteAll == null || !StringUtils.equalsIgnoreCase(ALL, this.deleteAll)) {
+ usage();
+ return null;
+ }
+ LOG.debug("Executing vtep:schema-delete command\t {} ", this.deleteAll);
+ this.itmProvider.deleteAllVtepSchemas();
+
+ } catch (IllegalArgumentException e) {
+ System.out.println(e.getMessage());
+ } catch (Exception e) {
+ LOG.error("Exception occurred during execution of command \"vtep:schema-delete all\": ", e);
+ }
+ 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.itm.cli;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.vpnservice.itm.api.IITMProvider;
+import org.opendaylight.vpnservice.itm.globals.ITMConstants;
+import org.opendaylight.vpnservice.itm.impl.ItmUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.VtepConfigSchema;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The Class which implements karaf command "vtep:schema-show".
+ */
+@Command(scope = "vtep", name = "schema-show", description = "Show all VTEP schemas.")
+public class VtepSchemaShow extends OsgiCommandSupport {
+
+ /** The schema name. */
+ @Argument(index = 0, name = "schemaName", description = "Schema name", required = false, multiValued = false)
+ private String schemaName;
+
+ private static String VTEP_CONFIG_SCHEMA_CLI_FORMAT = "%-14s %-12s %-8s %-16s %-13s %-14s %-11s %-20s %-32s";
+ public static final String HEADER_UNDERLINE = "---------------------------------------------------------------------------------------------------------------------------------------";
+
+ /** The Constant logger. */
+ private static final Logger LOG = LoggerFactory.getLogger(VtepSchemaShow.class);
+
+ /** The itm provider. */
+ private IITMProvider itmProvider;
+
+ /**
+ * Sets the itm provider.
+ *
+ * @param itmProvider
+ * the new itm provider
+ */
+ public void setItmProvider(IITMProvider itmProvider) {
+ this.itmProvider = itmProvider;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.karaf.shell.console.AbstractAction#doExecute()
+ */
+ @Override
+ protected Object doExecute() {
+ LOG.debug("Executing command: schema-show {} ", this.schemaName);
+ try {
+ if (this.schemaName != null) {
+ VtepConfigSchema schema = this.itmProvider.getVtepConfigSchema(this.schemaName);
+ if (schema == null) {
+ System.out.println("No VTEP schema present with name: " + this.schemaName);
+ } else {
+ System.out.println(getHeaderOutput());
+ printSchema(schema);
+ }
+ } else {
+ printAllVtepSchemas();
+ }
+ } catch (Exception e) {
+ LOG.error("Exception occurred during execution of command \"vtep:schema-show\": ", e);
+ }
+ return null;
+ }
+
+ /**
+ * Prints all vtep schemas.
+ */
+ private void printAllVtepSchemas() {
+ List<VtepConfigSchema> schemas = this.itmProvider.getAllVtepConfigSchemas();
+ if (schemas == null || schemas.isEmpty()) {
+ System.out.println("No VTEP schemas present.");
+ return;
+ }
+ System.out.println(getHeaderOutput());
+ for (VtepConfigSchema schema : schemas) {
+ printSchema(schema);
+ }
+ }
+
+ /**
+ * Prints the schema.
+ *
+ * @param schema
+ * the schema
+ */
+ private void printSchema(VtepConfigSchema schema) {
+ List<BigInteger> lstDpnIds = (schema.getDpnIds() == null) ? Collections.<BigInteger> emptyList()
+ : ItmUtils.getDpnIdList(schema.getDpnIds());
+ List<String> lstIpFilter = getExcludeIpFilterAsList(schema.getExcludeIpFilter());
+
+ Iterator<BigInteger> dpnIterator = lstDpnIds.iterator();
+ Iterator<String> ipFilterIterator = lstIpFilter.iterator();
+
+ String portName = StringUtils.defaultString(schema.getPortName());
+ String vlanId = String.valueOf(schema.getVlanId());
+ String subnetCIDR = (schema.getSubnet() == null) ? StringUtils.EMPTY
+ : String.valueOf(schema.getSubnet().getValue());
+ String gatewayIp = (schema.getGatewayIp() == null) ? StringUtils.EMPTY
+ : String.valueOf(schema.getGatewayIp().getValue());
+ String transportZone = StringUtils.defaultString(schema.getTransportZoneName());
+ String strTunnelType ;
+
+ Class<? extends TunnelTypeBase> tunType = schema.getTunnelType();
+
+ if( tunType.equals(TunnelTypeGre.class) )
+ strTunnelType = ITMConstants.TUNNEL_TYPE_GRE ;
+ else
+ strTunnelType = ITMConstants.TUNNEL_TYPE_VXLAN ;
+ String dpnId = (dpnIterator.hasNext() ? String.valueOf(dpnIterator.next()) : StringUtils.EMPTY);
+ String excludeIpFilter = (ipFilterIterator.hasNext() ? String.valueOf(ipFilterIterator.next())
+ : StringUtils.EMPTY);
+
+ // Print first row
+ System.out.println(String.format(VTEP_CONFIG_SCHEMA_CLI_FORMAT, schema.getSchemaName(), portName, vlanId,
+ subnetCIDR, gatewayIp, transportZone, strTunnelType, dpnId, excludeIpFilter));
+ while (dpnIterator.hasNext() || ipFilterIterator.hasNext()) {
+ dpnId = (dpnIterator.hasNext() ? String.valueOf(dpnIterator.next()) : StringUtils.EMPTY);
+ excludeIpFilter = (ipFilterIterator.hasNext() ? String.valueOf(ipFilterIterator.next())
+ : StringUtils.EMPTY);
+ System.out.println(String.format(VTEP_CONFIG_SCHEMA_CLI_FORMAT, StringUtils.EMPTY, StringUtils.EMPTY,
+ StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY, StringUtils.EMPTY,
+ dpnId, excludeIpFilter));
+ }
+ System.out.println(System.lineSeparator());
+ }
+
+ /**
+ * Gets the exclude ip filter as list.
+ *
+ * @param excludeIpFilter
+ * the exclude ip filter
+ * @return the exclude ip filter as list
+ */
+ private List<String> getExcludeIpFilterAsList(String excludeIpFilter) {
+ if (StringUtils.isBlank(excludeIpFilter)) {
+ return Collections.emptyList();
+ }
+ final String[] arrIpsOrRange = StringUtils.split(excludeIpFilter, ',');
+ return Arrays.asList(arrIpsOrRange);
+ }
+
+ /**
+ * Gets the vtep config schema header output.
+ *
+ * @return the vtep config schema header output
+ */
+ private String getHeaderOutput() {
+ StringBuilder headerBuilder = new StringBuilder();
+ headerBuilder.append(String.format(VTEP_CONFIG_SCHEMA_CLI_FORMAT, "SchemaName", "PortName", "VlanID", "Subnet",
+ "GatewayIP", "TransportZone", "TunnelType", "DPN-IDS", "ExcludeIpFilter"));
+ headerBuilder.append('\n');
+ headerBuilder.append(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.itm.cli;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.vpnservice.itm.api.IITMProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The Class which implements karaf command "vtep:schema-update".
+ */
+@Command(scope = "vtep", name = "schema-update", description = "Update VTEP schema.")
+public class VtepSchemaUpdate extends OsgiCommandSupport {
+
+ private static final String SCHEMA_NAME = "--schema-name";
+ private static final String AD = "--add-dpn-ids";
+ private static final String DD = "--del-dpn-ids";
+
+ /** The schema name. */
+ @Option(name = SCHEMA_NAME, aliases = { "-s" }, description = "Schema name", required = true, multiValued = false)
+ private String schemaName;
+
+ /** The dpn ids for add. */
+ @Option(name = AD, aliases = {
+ "-ad" }, description = "DPN ID's to be added to schema in a comma separated value format. e.g: 2,3,10", required = false, multiValued = false)
+ private String dpnIdsForAdd;
+
+ /** The dpn ids for delete. */
+ @Option(name = DD, aliases = {
+ "-dd" }, description = "DPN ID's to be deleted from schema in a comma separated value format. e.g: 2,3,10", required = false, multiValued = false)
+ private String dpnIdsForDelete;
+
+ /** The Constant logger. */
+ private static final Logger LOG = LoggerFactory.getLogger(VtepSchemaUpdate.class);
+
+ /** The itm provider. */
+ private IITMProvider itmProvider;
+
+ /**
+ * Sets the itm provider.
+ *
+ * @param itmProvider
+ * the new itm provider
+ */
+ public void setItmProvider(IITMProvider itmProvider) {
+ this.itmProvider = itmProvider;
+ }
+
+ /**
+ * Command Usage.
+ */
+ private void usage() {
+ System.out.println(
+ String.format("usage: vtep:schema-update [%s schema-name] [%s dpn-ids-for-add] [%s dpn-ids-for-delete]",
+ SCHEMA_NAME, AD, DD));
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.karaf.shell.console.AbstractAction#doExecute()
+ */
+ @Override
+ protected Object doExecute() {
+ try {
+ if (this.dpnIdsForAdd == null && this.dpnIdsForDelete == null) {
+ System.out.println(String.format("Atleast one of the parameters [%s or %s] is mandatory", AD, DD));
+ usage();
+ return null;
+ }
+ LOG.debug("Executing vtep:schema-update command\t {} \t {} \t {} ", this.schemaName, this.dpnIdsForAdd,
+ this.dpnIdsForDelete);
+
+ this.itmProvider.updateVtepSchema(this.schemaName, ItmCliUtils.constructDpnIdList(this.dpnIdsForAdd),
+ ItmCliUtils.constructDpnIdList(this.dpnIdsForDelete));
+
+ } catch (IllegalArgumentException e) {
+ System.out.println(e.getMessage());
+ } catch (Exception e) {
+ LOG.error("Exception occurred during execution of command \"vtep:schema-update\": ", e);
+ }
+ 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.itm.confighelpers;
+
+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.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
+
+/**
+ * Created by eanraju on 02-Feb-16.
+ */
+public class HwVtep {
+
+ private String transportZone;
+ private Class<? extends TunnelTypeBase> tunnel_type;
+ private IpPrefix ipPrefix;
+ private IpAddress gatewayIP;
+ private int vlanID;
+ private String topo_id;
+ private String node_id;
+ IpAddress hwIp;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ HwVtep HwVtep = (HwVtep) o;
+
+ if (vlanID != HwVtep.vlanID) return false;
+ if (!transportZone.equals(HwVtep.transportZone)) return false;
+ if (tunnel_type != null ? !tunnel_type.equals(HwVtep.tunnel_type) : HwVtep.tunnel_type != null) return false;
+ if (!ipPrefix.equals(HwVtep.ipPrefix)) return false;
+ if (gatewayIP != null ? !gatewayIP.equals(HwVtep.gatewayIP) : HwVtep.gatewayIP != null) return false;
+ if (!topo_id.equals(HwVtep.topo_id)) return false;
+ if (!node_id.equals(HwVtep.node_id)) return false;
+ return hwIp.equals(HwVtep.hwIp);
+
+ }
+
+ @Override
+ public String toString() {
+ return "HwVtep{" +
+ "transportZone='" + transportZone + '\'' +
+ ", tunnel_type=" + tunnel_type +
+ ", ipPrefix=" + ipPrefix +
+ ", gatewayIP=" + gatewayIP +
+ ", vlanID=" + vlanID +
+ ", topo_id='" + topo_id + '\'' +
+ ", node_id='" + node_id + '\'' +
+ ", hwIp=" + hwIp +
+ '}';
+ }
+
+ @Override
+ public int hashCode() {
+ int result = transportZone.hashCode();
+ result = 31 * result + (tunnel_type != null ? tunnel_type.hashCode() : 0);
+ result = 31 * result + ipPrefix.hashCode();
+ result = 31 * result + (gatewayIP != null ? gatewayIP.hashCode() : 0);
+ result = 31 * result + vlanID;
+ result = 31 * result + topo_id.hashCode();
+ result = 31 * result + node_id.hashCode();
+ result = 31 * result + hwIp.hashCode();
+ return result;
+ }
+
+ public String getTransportZone() {
+ return transportZone;
+ }
+
+ public void setTransportZone(String transportZone) {
+ this.transportZone = transportZone;
+ }
+
+ public Class<? extends TunnelTypeBase> getTunnel_type() {
+ return tunnel_type;
+ }
+
+ public void setTunnel_type(Class<? extends TunnelTypeBase> tunnel_type) {
+ this.tunnel_type = tunnel_type;
+ }
+
+ public IpPrefix getIpPrefix() {
+ return ipPrefix;
+ }
+
+ public void setIpPrefix(IpPrefix ipPrefix) {
+ this.ipPrefix = ipPrefix;
+ }
+
+ public IpAddress getGatewayIP() {
+ return gatewayIP;
+ }
+
+ public void setGatewayIP(IpAddress gatewayIP) {
+ this.gatewayIP = gatewayIP;
+ }
+
+ public int getVlanID() {
+ return vlanID;
+ }
+
+ public void setVlanID(int vlanID) {
+ this.vlanID = vlanID;
+ }
+
+ public String getTopo_id() {
+ return topo_id;
+ }
+
+ public void setTopo_id(String topo_id) {
+ this.topo_id = topo_id;
+ }
+
+ public String getNode_id() {
+ return node_id;
+ }
+
+ public void setNode_id(String node_id) {
+ this.node_id = node_id;
+ }
+
+ public IpAddress getHwIp() {
+ return hwIp;
+ }
+
+ public void setHwIp(IpAddress hwIp) {
+ this.hwIp = hwIp;
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.itm.confighelpers;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.itm.globals.ITMConstants;
+import org.opendaylight.vpnservice.itm.impl.ItmUtils;
+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.inet.types.rev100924.IpPrefix;
+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.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.ExternalTunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnelKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnelKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZone;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZoneKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.DeviceVteps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.Vteps;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.*;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.commons.net.util.SubnetUtils;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class ItmExternalTunnelAddWorker {
+ private static final Logger logger = LoggerFactory.getLogger(ItmExternalTunnelAddWorker.class);
+
+ private 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 List<ListenableFuture<Void>> buildTunnelsToExternalEndPoint(DataBroker dataBroker, IdManagerService idManagerService,
+ List<DPNTEPsInfo> cfgDpnList, IpAddress extIp, Class<? extends TunnelTypeBase> tunType) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ if (null != cfgDpnList) {
+ for (DPNTEPsInfo teps : cfgDpnList) {
+ // CHECK -- Assumption -- Only one End Point / Dpn for GRE/Vxlan Tunnels
+ TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0);
+ String interfaceName = firstEndPt.getInterfaceName();
+ String tunTypeStr = tunType.getName();
+ String trunkInterfaceName = ItmUtils.getTrunkInterfaceName(idManagerService, interfaceName, firstEndPt.getIpAddress().getIpv4Address().getValue(), extIp.getIpv4Address().getValue(), tunTypeStr);
+ char[] subnetMaskArray = firstEndPt.getSubnetMask().getValue();
+ String subnetMaskStr = String.valueOf(subnetMaskArray);
+ SubnetUtils utils = new SubnetUtils(subnetMaskStr);
+ String dcGwyIpStr = String.valueOf(extIp.getValue());
+ IpAddress gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
+ IpAddress gwyIpAddress = (utils.getInfo().isInRange(dcGwyIpStr)) ? gatewayIpObj : firstEndPt.getGwIpAddress();
+ logger.debug(" Creating Trunk Interface with parameters trunk I/f Name - {}, parent I/f name - {}, source IP - {}, DC Gateway IP - {} gateway IP - {}", trunkInterfaceName, interfaceName, firstEndPt.getIpAddress(), extIp, gwyIpAddress);
+ Interface iface = ItmUtils.buildTunnelInterface(teps.getDPNID(), trunkInterfaceName, String.format("%s %s", ItmUtils.convertTunnelTypetoString(tunType), "Trunk Interface"), true, tunType, firstEndPt.getIpAddress(), extIp, gwyIpAddress, firstEndPt.getVLANID(), false,false,null);
+ logger.debug(" Trunk Interface builder - {} ", iface);
+ InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(trunkInterfaceName);
+ logger.debug(" Trunk Interface Identifier - {} ", trunkIdentifier);
+ logger.trace(" Writing Trunk Interface to Config DS {}, {} ", trunkIdentifier, iface);
+ t.merge(LogicalDatastoreType.CONFIGURATION, trunkIdentifier, iface, true);
+ // update external_tunnel_list ds
+ InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
+ ExternalTunnelList.class)
+ .child(ExternalTunnel.class, new ExternalTunnelKey(extIp.toString(), teps.getDPNID().toString(), tunType));
+ ExternalTunnel tnl = ItmUtils.buildExternalTunnel( teps.getDPNID().toString(), extIp.toString(),
+ tunType, trunkInterfaceName);
+ t.merge(LogicalDatastoreType.CONFIGURATION, path, tnl, true);
+ }
+ futures.add(t.submit());
+ }
+ return futures;
+ }
+
+ public static List<ListenableFuture<Void>> buildTunnelsFromDpnToExternalEndPoint(DataBroker dataBroker, IdManagerService idManagerService,
+ List<BigInteger> dpnId, IpAddress extIp, Class<? extends TunnelTypeBase> tunType) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ List<DPNTEPsInfo> cfgDpnList = (dpnId == null) ? ItmUtils.getTunnelMeshInfo(dataBroker) : ItmUtils.getDPNTEPListFromDPNId(dataBroker, dpnId);
+ futures = buildTunnelsToExternalEndPoint(dataBroker, idManagerService, cfgDpnList, extIp, tunType);
+ return futures;
+ }
+
+ public static List<ListenableFuture<Void>> buildHwVtepsTunnels(DataBroker dataBroker, IdManagerService idManagerService, List<DPNTEPsInfo> cfgdDpnList, List<HwVtep> cfgdHwVteps) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ if (null != cfgdDpnList && !cfgdDpnList.isEmpty()) {
+ logger.trace("calling tunnels from css {}",cfgdDpnList);
+ tunnelsFromCSS(cfgdDpnList, idManagerService , futures, t , dataBroker);
+
+ }
+ if (null != cfgdHwVteps && !cfgdHwVteps.isEmpty() ) {
+ logger.trace("calling tunnels from hwTep {}",cfgdHwVteps);
+ tunnelsFromhWVtep(cfgdHwVteps, idManagerService, futures, t, dataBroker);
+ }
+
+ if ((cfgdDpnList != null && !cfgdDpnList.isEmpty()) || (cfgdHwVteps != null && !cfgdHwVteps.isEmpty()))
+ futures.add(t.submit());
+ return futures;
+ }
+
+ private static void tunnelsFromCSS(List<DPNTEPsInfo> cfgdDpnList, IdManagerService idManagerService, List<ListenableFuture<Void>> futures, WriteTransaction t, DataBroker dataBroker) {
+ for (DPNTEPsInfo dpn : cfgdDpnList) {
+ logger.trace("processing dpn {}" , dpn);
+ if (dpn.getTunnelEndPoints() != null && !dpn.getTunnelEndPoints().isEmpty())
+ for (TunnelEndPoints tep : dpn.getTunnelEndPoints()) {
+ InstanceIdentifier<TransportZone> tzonePath = InstanceIdentifier.builder(TransportZones.class).child(TransportZone.class, new TransportZoneKey((tep.getTransportZone()))).build();
+ Optional<TransportZone> tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, dataBroker);
+ if (tZoneOptional.isPresent()) {
+ TransportZone tZone = tZoneOptional.get();
+ //do we need to check tunnel type?
+ if (tZone.getSubnets() != null && !tZone.getSubnets().isEmpty()) {
+ for (Subnets sub : tZone.getSubnets()) {
+ if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) {
+ for (DeviceVteps hwVtepDS : sub.getDeviceVteps()) {
+ String cssID = dpn.getDPNID().toString();
+ String nodeId = hwVtepDS.getNodeId();
+ //CSS-TOR
+ Boolean monitorEnabled = ItmUtils.readMonitoringStateFromDS(dataBroker);
+ Integer monitorInterval = ItmUtils.readMonitorIntervalfromDS(dataBroker);
+ logger.trace("wire up {} and {}",tep, hwVtepDS);
+ if (!wireUp(dpn.getDPNID(), tep.getPortname(), sub.getVlanId(), tep.getIpAddress(), nodeId, hwVtepDS.getIpAddress(), tep.getSubnetMask(),
+ sub.getGatewayIp(), sub.getPrefix(), tZone.getTunnelType(),monitorEnabled,ITMConstants.BFD_DEFAULT_MONITOR_INTERVAL, idManagerService, dataBroker, futures, t))
+ logger.error("Unable to build tunnel {} -- {}", tep.getIpAddress(), hwVtepDS.getIpAddress());
+ //TOR-CSS
+ logger.trace("wire up {} and {}", hwVtepDS,tep);
+ if (!wireUp(hwVtepDS.getTopologyId(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(), cssID, tep.getIpAddress(), sub.getPrefix(),
+ sub.getGatewayIp(), tep.getSubnetMask(), tZone.getTunnelType(), monitorEnabled,ITMConstants.BFD_DEFAULT_MONITOR_INTERVAL, idManagerService, dataBroker, futures, t))
+ logger.error("Unable to build tunnel {} -- {}", hwVtepDS.getIpAddress(), tep.getIpAddress());
+
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private static void tunnelsFromhWVtep(List<HwVtep> cfgdHwVteps, IdManagerService idManagerService, List<ListenableFuture<Void>> futures, WriteTransaction t, DataBroker dataBroker) {
+ for (HwVtep hwTep : cfgdHwVteps) {
+ InstanceIdentifier<TransportZone> tzonePath = InstanceIdentifier.builder(TransportZones.class).child(TransportZone.class, new TransportZoneKey((hwTep.getTransportZone()))).build();
+ Optional<TransportZone> tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, dataBroker);
+ Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
+ if (tZoneOptional.isPresent()) {
+ TransportZone tZone = tZoneOptional.get();
+ //do we need to check tunnel type?
+ if (tZone.getSubnets() != null && !tZone.getSubnets().isEmpty()) {
+ for (Subnets sub : tZone.getSubnets()) {
+ if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) {
+ for (DeviceVteps hwVtepDS : sub.getDeviceVteps()) {
+ if (hwVtepDS.getIpAddress().equals(hwTep.getHwIp()))
+ continue;//dont mesh with self
+ //TOR1-TOR2
+ Boolean monitorEnabled = ItmUtils.readMonitoringStateFromDS(dataBroker);
+ Integer monitorInterval = ItmUtils.readMonitorIntervalfromDS(dataBroker);
+ logger.trace("wire up {} and {}",hwTep, hwVtepDS);
+ if (!wireUp(hwTep.getTopo_id(), hwTep.getNode_id(), hwTep.getHwIp(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(),
+ hwTep.getIpPrefix(), hwTep.getGatewayIP(), sub.getPrefix(), tunType,monitorEnabled,
+ ITMConstants.BFD_DEFAULT_MONITOR_INTERVAL, idManagerService, dataBroker, futures, t))
+ logger.error("Unable to build tunnel {} -- {}", hwTep.getHwIp(), hwVtepDS.getIpAddress());
+ //TOR2-TOR1
+ logger.trace("wire up {} and {}", hwVtepDS,hwTep);
+ if (!wireUp(hwTep.getTopo_id(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(), hwTep.getNode_id(), hwTep.getHwIp(),
+ sub.getPrefix(), sub.getGatewayIp(), hwTep.getIpPrefix(), tunType, monitorEnabled,ITMConstants.BFD_DEFAULT_MONITOR_INTERVAL, idManagerService, dataBroker, futures, t))
+ logger.error("Unable to build tunnel {} -- {}", hwVtepDS.getIpAddress(), hwTep.getHwIp());
+ }
+ }
+ if (sub.getVteps() != null && !sub.getVteps().isEmpty()) {
+ for (Vteps vtep : sub.getVteps()) {
+ //TOR-CSS
+ String cssID = vtep.getDpnId().toString();
+ Boolean monitorEnabled = ItmUtils.readMonitoringStateFromDS(dataBroker);
+ Integer monitorInterval = ItmUtils.readMonitorIntervalfromDS(dataBroker);
+ logger.trace("wire up {} and {}",hwTep, vtep);
+ if(!wireUp(hwTep.getTopo_id(), hwTep.getNode_id(), hwTep.getHwIp(), cssID, vtep.getIpAddress(), hwTep.getIpPrefix(),
+ hwTep.getGatewayIP(), sub.getPrefix(), tunType,monitorEnabled, ITMConstants.BFD_DEFAULT_MONITOR_INTERVAL, idManagerService, dataBroker, futures, t ))
+ logger.error("Unable to build tunnel {} -- {}", hwTep.getHwIp(), vtep.getIpAddress());
+ //CSS-TOR
+ logger.trace("wire up {} and {}", vtep,hwTep);
+ if(!wireUp(vtep.getDpnId(), vtep.getPortname(), sub.getVlanId(), vtep.getIpAddress(),
+ hwTep.getNode_id(),hwTep.getHwIp(),sub.getPrefix(), sub.getGatewayIp(),hwTep.getIpPrefix(),
+ tunType,monitorEnabled,ITMConstants.BFD_DEFAULT_MONITOR_INTERVAL,idManagerService, dataBroker, futures, t ));
+
+ }
+
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //for tunnels from TOR device
+ private static boolean wireUp(String topo_id, String srcNodeid, IpAddress srcIp, String dstNodeId, IpAddress dstIp, IpPrefix srcSubnet,
+ IpAddress gWIp, IpPrefix dstSubnet, Class<? extends TunnelTypeBase> tunType,Boolean monitorEnabled,
+ Integer monitorInterval,IdManagerService idManagerService, DataBroker dataBroker, List<ListenableFuture<Void>> futures, WriteTransaction t) {
+ IpAddress gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
+ IpAddress gwyIpAddress = (srcSubnet.equals(dstSubnet)) ? gatewayIpObj : gWIp;
+ String parentIf = ItmUtils.getHwParentIf(topo_id, srcNodeid);
+ String tunTypeStr = tunType.getName();
+ String tunnelIfName = ItmUtils.getTrunkInterfaceName(idManagerService, parentIf,
+ srcIp.getIpv4Address().getValue(), dstIp.getIpv4Address().getValue(), tunTypeStr);
+ logger.debug(" Creating ExternalTrunk Interface with parameters Name - {}, parent I/f name - {}, source IP - {}, destination IP - {} gateway IP - {}", tunnelIfName, parentIf, srcIp, dstIp, gwyIpAddress);
+ Interface hwTunnelIf = ItmUtils.buildHwTunnelInterface(tunnelIfName, String.format("%s %s", tunType.getName(), "Trunk Interface"),
+ true, topo_id, srcNodeid, tunType, srcIp, dstIp, gwyIpAddress, monitorEnabled, monitorInterval);
+ InstanceIdentifier<Interface> ifIID = InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(tunnelIfName)).build();
+ logger.trace(" Writing Trunk Interface to Config DS {}, {} ", ifIID, hwTunnelIf);
+ ItmUtils.itmCache.addInterface(hwTunnelIf);
+ t.merge(LogicalDatastoreType.CONFIGURATION, ifIID, hwTunnelIf, true);
+ // also update itm-state ds?
+ InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
+ ExternalTunnelList.class)
+ .child(ExternalTunnel.class, new ExternalTunnelKey( getExternalTunnelKey(dstNodeId), getExternalTunnelKey(srcNodeid), tunType));
+ ExternalTunnel tnl = ItmUtils.buildExternalTunnel( getExternalTunnelKey(srcNodeid),
+ getExternalTunnelKey(dstNodeId),
+ tunType, tunnelIfName);
+ t.merge(LogicalDatastoreType.CONFIGURATION, path, tnl, true);
+ ItmUtils.itmCache.addExternalTunnel(tnl);
+ return true;
+ }
+
+ //for tunnels from CSS
+ private static boolean wireUp(BigInteger dpnId,String portname, Integer vlanId, IpAddress srcIp, String dstNodeId, IpAddress dstIp, IpPrefix srcSubnet,
+ IpAddress gWIp, IpPrefix dstSubnet, Class<? extends TunnelTypeBase> tunType,Boolean monitorEnabled, Integer monitorInterval,
+ IdManagerService idManagerService, DataBroker dataBroker, List<ListenableFuture<Void>> futures, WriteTransaction t) {
+ IpAddress gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
+ IpAddress gwyIpAddress = (srcSubnet.equals(dstSubnet)) ? gatewayIpObj : gWIp;
+ String parentIf = ItmUtils.getInterfaceName(dpnId, portname, vlanId);
+ String tunTypeStr = tunType.getName();
+ String tunnelIfName = ItmUtils.getTrunkInterfaceName(idManagerService, parentIf,
+ srcIp.getIpv4Address().getValue(), dstIp.getIpv4Address().getValue(), tunTypeStr);
+ logger.debug(" Creating ExternalTrunk Interface with parameters Name - {}, parent I/f name - {}, source IP - {}, destination IP - {} gateway IP - {}", tunnelIfName, parentIf, srcIp, dstIp, gwyIpAddress);
+ Interface extTunnelIf = ItmUtils.buildTunnelInterface(dpnId, tunnelIfName, String.format("%s %s", tunType.getName(), "Trunk Interface"), true, tunType, srcIp, dstIp, gwyIpAddress, vlanId, false,monitorEnabled, monitorInterval);
+ InstanceIdentifier<Interface> ifIID = InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(tunnelIfName)).build();
+ logger.trace(" Writing Trunk Interface to Config DS {}, {} ", ifIID, extTunnelIf);
+ t.merge(LogicalDatastoreType.CONFIGURATION, ifIID, extTunnelIf, true);
+ ItmUtils.itmCache.addInterface(extTunnelIf);
+ InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
+ ExternalTunnelList.class)
+ .child(ExternalTunnel.class, new ExternalTunnelKey(getExternalTunnelKey(dstNodeId), dpnId.toString(), tunType));
+ ExternalTunnel tnl = ItmUtils.buildExternalTunnel( dpnId.toString(),
+ getExternalTunnelKey(dstNodeId),
+ tunType, tunnelIfName);
+ t.merge(LogicalDatastoreType.CONFIGURATION, path, tnl, true);
+ ItmUtils.itmCache.addExternalTunnel(tnl);
+ return true;
+ }
+
+ static String getExternalTunnelKey(String nodeid) {
+ if (nodeid.indexOf("physicalswitch") > 0) {
+ nodeid = nodeid.substring(0, nodeid.indexOf("physicalswitch") - 1);
+ }
+ return nodeid;
+ }
+}
+
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.itm.confighelpers;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.common.base.Optional;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.itm.globals.ITMConstants;
+import org.opendaylight.vpnservice.itm.impl.ItmUtils;
+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.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.ExternalTunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnelKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZone;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZoneKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.DeviceVteps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.Vteps;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class ItmExternalTunnelDeleteWorker {
+ private static final Logger logger = LoggerFactory.getLogger(ItmExternalTunnelDeleteWorker.class ) ;
+
+ public static List<ListenableFuture<Void>> deleteTunnels(DataBroker dataBroker, IdManagerService idManagerService, List<DPNTEPsInfo> dpnTepsList,IpAddress extIp, Class<? extends TunnelTypeBase> tunType ) {
+ logger.trace( " Delete Tunnels towards DC Gateway with Ip {}", extIp ) ;
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+
+ if (dpnTepsList == null || dpnTepsList.size() == 0) {
+ logger.debug("no vtep to delete");
+ return null ;
+ }
+ for( DPNTEPsInfo teps : dpnTepsList) {
+ TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0) ;
+ String interfaceName = firstEndPt.getInterfaceName() ;
+ String trunkInterfaceName = ItmUtils.getTrunkInterfaceName( idManagerService, interfaceName,
+ firstEndPt.getIpAddress().getIpv4Address().getValue(),
+ extIp.getIpv4Address().getValue(),
+ tunType.getName());
+ InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(trunkInterfaceName);
+ t.delete(LogicalDatastoreType.CONFIGURATION, trunkIdentifier);
+ ItmUtils.itmCache.removeInterface(trunkInterfaceName);
+
+ InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
+ ExternalTunnelList.class)
+ .child(ExternalTunnel.class, ItmUtils.getExternalTunnelKey(extIp.toString(),
+ teps.getDPNID().toString(),
+ tunType));
+ t.delete(LogicalDatastoreType.CONFIGURATION, path);
+ logger.debug( "Deleting tunnel towards DC gateway, Tunnel interface name {} ",trunkInterfaceName );
+ ItmUtils.itmCache.removeExternalTunnel(trunkInterfaceName);
+ // Release the Ids for the trunk interface Name
+ ItmUtils.releaseIdForTrunkInterfaceName(idManagerService,interfaceName,firstEndPt.getIpAddress().getIpv4Address().getValue(), extIp.getIpv4Address().getValue(),tunType.getName());
+ }
+ futures.add(t.submit()) ;
+ return futures ;
+ }
+
+ public static List<ListenableFuture<Void>> deleteHwVtepsTunnels(DataBroker dataBroker, IdManagerService idManagerService, List<DPNTEPsInfo> delDpnList ,List<HwVtep> cfgdHwVteps) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+
+ if (delDpnList != null || cfgdHwVteps != null)
+ tunnelsDeletion(delDpnList, cfgdHwVteps, idManagerService, futures, t, dataBroker);
+ futures.add(t.submit());
+ return futures;
+ }
+
+ private static void tunnelsDeletion(List<DPNTEPsInfo> cfgdDpnList, List<HwVtep> cfgdhwVteps, IdManagerService idManagerService, List<ListenableFuture<Void>> futures, WriteTransaction t, DataBroker dataBroker) {
+ if (cfgdDpnList != null && !cfgdDpnList.isEmpty()) {
+ for (DPNTEPsInfo dpn : cfgdDpnList) {
+ if (dpn.getTunnelEndPoints() != null && !dpn.getTunnelEndPoints().isEmpty())
+ for (TunnelEndPoints srcTep : dpn.getTunnelEndPoints()) {
+ InstanceIdentifier<TransportZone> tzonePath = InstanceIdentifier.builder(TransportZones.class)
+ .child(TransportZone.class, new TransportZoneKey((srcTep.getTransportZone())))
+ .build();
+ Optional<TransportZone> tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, dataBroker);
+ if (tZoneOptional.isPresent()) {
+ TransportZone tZone = tZoneOptional.get();
+ //do we need to check tunnel type?
+ if (tZone.getSubnets() != null && !tZone.getSubnets().isEmpty()) {
+ for (Subnets sub : tZone.getSubnets()) {
+ if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) {
+ for (DeviceVteps hwVtepDS : sub.getDeviceVteps()) {
+ String cssID = dpn.getDPNID().toString();
+ //CSS-TOR-CSS
+ deleteTrunksCSSTOR(dataBroker, idManagerService, dpn.getDPNID(), srcTep.getInterfaceName(), srcTep.getIpAddress(),
+ hwVtepDS.getTopologyId(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(), tZone.getTunnelType(),
+ t, futures);
+ }
+ }
+ }
+ }
+ if (cfgdhwVteps != null && !cfgdhwVteps.isEmpty()) {
+ for (HwVtep hwVtep : cfgdhwVteps) {
+ deleteTrunksCSSTOR(dataBroker, idManagerService, dpn.getDPNID(), srcTep.getInterfaceName(), srcTep.getIpAddress(),
+ hwVtep.getTopo_id(), hwVtep.getNode_id(), hwVtep.getHwIp(),
+ TunnelTypeVxlan.class, t, futures);
+ }
+ }
+ }
+ }
+ }
+ }
+ if (cfgdhwVteps != null && !cfgdhwVteps.isEmpty()) {
+ for (HwVtep hwTep : cfgdhwVteps) {
+ logger.trace("processing hwTep from list {}", hwTep);
+ for (HwVtep hwTepRemote : cfgdhwVteps) {
+ if (!hwTep.getHwIp().equals(hwTepRemote.getHwIp())) {
+ deleteTrunksTORTOR(dataBroker, idManagerService, hwTep.getTopo_id(), hwTep.getNode_id(),
+ hwTep.getHwIp(), hwTepRemote.getTopo_id(), hwTepRemote.getNode_id(),
+ hwTepRemote.getHwIp(), TunnelTypeVxlan.class, t, futures);
+ }
+ }
+ InstanceIdentifier<TransportZone> tzonePath = InstanceIdentifier.builder(TransportZones.class)
+ .child(TransportZone.class, new TransportZoneKey((hwTep.getTransportZone()))).build();
+ Optional<TransportZone> tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath, dataBroker);
+ if (tZoneOptional.isPresent()) {
+ TransportZone tZone = tZoneOptional.get();
+ logger.trace("subnets under tz {} are {}", tZone.getZoneName(), tZone.getSubnets());
+ if (tZone.getSubnets() != null && !tZone.getSubnets().isEmpty()) {
+ for (Subnets sub : tZone.getSubnets()) {
+ if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) {
+ for (DeviceVteps hwVtepDS : sub.getDeviceVteps()) {
+ logger.trace("hwtepDS exists {}", hwVtepDS);
+ if (hwVtepDS.getIpAddress().equals(hwTep.getHwIp()))
+ continue;//dont delete tunnels with self
+ logger.trace("deleting tor-tor {} and {}", hwTep, hwVtepDS);
+ deleteTrunksTORTOR(dataBroker, idManagerService, hwTep.getTopo_id(), hwTep.getNode_id(),
+ hwTep.getHwIp(), hwVtepDS.getTopologyId(), hwVtepDS.getNodeId(),
+ hwVtepDS.getIpAddress(), tZone.getTunnelType(),
+ t, futures);
+
+ }
+ }
+ if (sub.getVteps() != null && !sub.getVteps().isEmpty()) {
+ for (Vteps vtep : sub.getVteps()) {
+ logger.trace("deleting tor-css-tor {} and {}", hwTep, vtep);
+ String parentIf = ItmUtils.getInterfaceName(vtep.getDpnId(), vtep.getPortname(), sub.getVlanId());
+ deleteTrunksCSSTOR(dataBroker, idManagerService, vtep.getDpnId(), parentIf, vtep.getIpAddress(),
+ hwTep.getTopo_id(), hwTep.getNode_id(), hwTep.getHwIp(),
+ tZone.getTunnelType(), t, futures);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+
+
+
+ //do we need to check tunnel type?
+
+ //do i need to check node-id?
+ //for mlag case and non-m-lag case, isnt it enough to just check ipaddress?
+ //TOR-TOR
+
+ //TOR-CSS
+
+
+
+ private static void deleteTrunksCSSTOR(DataBroker dataBroker, IdManagerService idManagerService, BigInteger dpnid,
+ String interfaceName, IpAddress cssIpAddress, String topologyId, String nodeId, IpAddress hWIpAddress,
+ Class<? extends TunnelTypeBase> tunType, WriteTransaction t,
+ List<ListenableFuture<Void>> futures) {
+ //CSS-TOR
+ if (trunkExists(dpnid.toString(), nodeId, tunType, dataBroker)) {
+ logger.trace("deleting tunnel from {} to {} ", dpnid.toString(), nodeId);
+ String parentIf = interfaceName;
+ String fwdTrunkIf = ItmUtils.getTrunkInterfaceName(idManagerService,parentIf,cssIpAddress.getIpv4Address().getValue(),
+ hWIpAddress.getIpv4Address().getValue(), tunType.getName());
+ InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(fwdTrunkIf);
+ t.delete(LogicalDatastoreType.CONFIGURATION, trunkIdentifier);
+
+ InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
+ ExternalTunnelList.class)
+ .child(ExternalTunnel.class, ItmUtils.getExternalTunnelKey(nodeId, dpnid.toString(), tunType));
+ t.delete(LogicalDatastoreType.CONFIGURATION, path);
+ }
+ else {
+ logger.trace(" trunk from {} to {} already deleted",dpnid.toString(), nodeId);
+ }
+ //TOR-CSS
+ if (trunkExists( nodeId, dpnid.toString(), tunType, dataBroker)) {
+ logger.trace("deleting tunnel from {} to {} ",nodeId, dpnid.toString());
+
+ String parentIf = ItmUtils.getHwParentIf(topologyId,nodeId);
+ String revTrunkIf = ItmUtils.getTrunkInterfaceName(idManagerService,parentIf, hWIpAddress.getIpv4Address().getValue(),
+ cssIpAddress.getIpv4Address().getValue(), tunType.getName());
+ InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(revTrunkIf);
+ t.delete(LogicalDatastoreType.CONFIGURATION, trunkIdentifier);
+
+ InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
+ ExternalTunnelList.class)
+ .child(ExternalTunnel.class, ItmUtils.getExternalTunnelKey(dpnid.toString(),nodeId, tunType));
+ t.delete(LogicalDatastoreType.CONFIGURATION, path);
+ }
+ else {
+ logger.trace(" trunk from {} to {} already deleted", nodeId, dpnid.toString());
+ }
+ }
+
+ private static void deleteTrunksTORTOR(DataBroker dataBroker, IdManagerService idManagerService,
+ String topologyId1, String nodeId1, IpAddress hWIpAddress1, String topologyId2, String nodeId2, IpAddress hWIpAddress2,
+ Class<? extends TunnelTypeBase> tunType, WriteTransaction t, List<ListenableFuture<Void>> futures) {
+ //TOR1-TOR2
+ if (trunkExists(nodeId1, nodeId2, tunType, dataBroker)) {
+ logger.trace("deleting tunnel from {} to {} ", nodeId1, nodeId2);
+ String parentIf = ItmUtils.getHwParentIf(topologyId1,nodeId1);
+ String fwdTrunkIf = ItmUtils.getTrunkInterfaceName(idManagerService, parentIf,
+ hWIpAddress1.getIpv4Address().getValue(),
+ hWIpAddress2.getIpv4Address().getValue(),
+ tunType.getName());
+ InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(fwdTrunkIf);
+ t.delete(LogicalDatastoreType.CONFIGURATION, trunkIdentifier);
+
+ InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
+ ExternalTunnelList.class)
+ .child(ExternalTunnel.class, ItmUtils.getExternalTunnelKey(nodeId2, nodeId1, tunType));
+ t.delete(LogicalDatastoreType.CONFIGURATION, path);
+ }
+ else {
+ logger.trace(" trunk from {} to {} already deleted",nodeId1, nodeId2);
+ }
+ //TOR2-TOR1
+ if (trunkExists( nodeId2, nodeId1, tunType, dataBroker)) {
+ logger.trace("deleting tunnel from {} to {} ",nodeId2, nodeId1);
+
+ String parentIf = ItmUtils.getHwParentIf(topologyId2,nodeId2);
+ String revTrunkIf = ItmUtils.getTrunkInterfaceName(idManagerService,parentIf, hWIpAddress2.getIpv4Address().getValue(),
+ hWIpAddress1.getIpv4Address().getValue(), tunType.getName());
+ InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(revTrunkIf);
+ t.delete(LogicalDatastoreType.CONFIGURATION, trunkIdentifier);
+
+ InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
+ ExternalTunnelList.class)
+ .child(ExternalTunnel.class, ItmUtils.getExternalTunnelKey(nodeId1,nodeId2, tunType));
+ t.delete(LogicalDatastoreType.CONFIGURATION, path);
+ }
+ else {
+ logger.trace(" trunk from {} to {} already deleted",nodeId2, nodeId1);
+ }
+ }
+
+ private static boolean trunkExists( String srcDpnOrNode, String dstDpnOrNode,
+ Class<? extends TunnelTypeBase> tunType,DataBroker dataBroker) {
+ boolean existsFlag = false ;
+ InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
+ ExternalTunnelList.class)
+ .child(ExternalTunnel.class, ItmUtils.getExternalTunnelKey(dstDpnOrNode, srcDpnOrNode, tunType));
+ Optional<ExternalTunnel> exTunnels = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,path, dataBroker) ;
+ if( exTunnels.isPresent()) {
+ existsFlag = true ;
+ }
+ return existsFlag ;
+ }
+
+
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.itm.confighelpers;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.itm.globals.ITMConstants;
+import org.opendaylight.vpnservice.itm.impl.ItmUtils;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+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.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.DpnEndpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.DpnEndpointsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.ExternalTunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnelKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnelKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ItmInternalTunnelAddWorker {
+ private static final Logger logger = LoggerFactory.getLogger(ItmInternalTunnelAddWorker.class) ;
+ private 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 List<ListenableFuture<Void>> build_all_tunnels(DataBroker dataBroker, IdManagerService idManagerService,IMdsalApiManager mdsalManager,
+ List<DPNTEPsInfo> cfgdDpnList, List<DPNTEPsInfo> meshedDpnList) {
+ logger.trace( "Building tunnels with DPN List {} " , cfgdDpnList );
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ if( null == cfgdDpnList || cfgdDpnList.isEmpty()) {
+ logger.error(" Build Tunnels was invoked with empty list");
+ return futures;
+ }
+
+ for( DPNTEPsInfo dpn : cfgdDpnList) {
+ //#####if dpn is not in meshedDpnList
+ build_tunnel_from(dpn, meshedDpnList, dataBroker, idManagerService, mdsalManager, t, futures);
+ if(null == meshedDpnList) {
+ meshedDpnList = new ArrayList<DPNTEPsInfo>() ;
+ }
+ meshedDpnList.add(dpn) ;
+ // Update the operational datastore -- FIXME -- Error Handling
+ updateOperationalDatastore(dataBroker, dpn, t, futures) ;
+ }
+ futures.add( t.submit()) ;
+ return futures ;
+ }
+
+ private static void updateOperationalDatastore(DataBroker dataBroker, DPNTEPsInfo dpn, WriteTransaction t, List<ListenableFuture<Void>> futures) {
+ logger.debug("Updating CONFIGURATION datastore with DPN {} ", dpn);
+ InstanceIdentifier<DpnEndpoints> dep = InstanceIdentifier.builder( DpnEndpoints.class).build() ;
+ List<DPNTEPsInfo> dpnList = new ArrayList<DPNTEPsInfo>() ;
+ dpnList.add(dpn) ;
+ DpnEndpoints tnlBuilder = new DpnEndpointsBuilder().setDPNTEPsInfo(dpnList).build() ;
+ t.merge(LogicalDatastoreType.CONFIGURATION, dep, tnlBuilder, true);
+ }
+
+ private static void build_tunnel_from( DPNTEPsInfo srcDpn,List<DPNTEPsInfo> meshedDpnList, DataBroker dataBroker, IdManagerService idManagerService, IMdsalApiManager mdsalManager, WriteTransaction t, List<ListenableFuture<Void>> futures) {
+ logger.trace( "Building tunnels from DPN {} " , srcDpn );
+
+ if( null == meshedDpnList || 0 == meshedDpnList.size()) {
+ logger.debug( "No DPN in the mesh ");
+ return ;
+ }
+ for( DPNTEPsInfo dstDpn: meshedDpnList) {
+ if ( ! srcDpn.equals(dstDpn) )
+ wireUpWithinTransportZone(srcDpn, dstDpn, dataBroker, idManagerService, mdsalManager, t, futures) ;
+ }
+
+ }
+
+ private static void wireUpWithinTransportZone( DPNTEPsInfo srcDpn, DPNTEPsInfo dstDpn, DataBroker dataBroker,
+ IdManagerService idManagerService, IMdsalApiManager mdsalManager,WriteTransaction t, List<ListenableFuture<Void>> futures) {
+ logger.trace( "Wiring up within Transport Zone for Dpns {}, {} " , srcDpn, dstDpn );
+ List<TunnelEndPoints> srcEndPts = srcDpn.getTunnelEndPoints();
+ List<TunnelEndPoints> dstEndPts = dstDpn.getTunnelEndPoints();
+
+ for( TunnelEndPoints srcte : srcEndPts) {
+ for( TunnelEndPoints dstte : dstEndPts ) {
+ // Compare the Transport zones
+ if (!srcDpn.getDPNID().equals(dstDpn.getDPNID())) {
+ if( (srcte.getTransportZone().equals(dstte.getTransportZone()))) {
+ // wire them up
+ wireUpBidirectionalTunnel( srcte, dstte, srcDpn.getDPNID(), dstDpn.getDPNID(), dataBroker, idManagerService, mdsalManager, t, futures );
+ // CHECK THIS -- Assumption -- One end point per Dpn per transport zone
+ break ;
+ }
+ }
+ }
+ }
+ }
+
+ private static void wireUpBidirectionalTunnel( TunnelEndPoints srcte, TunnelEndPoints dstte, BigInteger srcDpnId, BigInteger dstDpnId,
+ DataBroker dataBroker, IdManagerService idManagerService, IMdsalApiManager mdsalManager, WriteTransaction t, List<ListenableFuture<Void>> futures) {
+ // Setup the flow for LLDP monitoring -- PUNT TO CONTROLLER
+ ItmUtils.setUpOrRemoveTerminatingServiceTable(srcDpnId, mdsalManager, true);
+ ItmUtils.setUpOrRemoveTerminatingServiceTable(dstDpnId, mdsalManager, true);
+
+ // Create the forward direction tunnel
+ if(!wireUp( srcte, dstte, srcDpnId, dstDpnId, dataBroker, idManagerService, t, futures ))
+ logger.error("Could not build tunnel between end points {}, {} " , srcte, dstte );
+
+ // CHECK IF FORWARD IS NOT BUILT , REVERSE CAN BE BUILT
+ // Create the tunnel for the reverse direction
+ if(! wireUp( dstte, srcte, dstDpnId, srcDpnId, dataBroker, idManagerService, t, futures ))
+ logger.error("Could not build tunnel between end points {}, {} " , dstte, srcte);
+ }
+
+ private static boolean wireUp(TunnelEndPoints srcte, TunnelEndPoints dstte, BigInteger srcDpnId, BigInteger dstDpnId ,
+ DataBroker dataBroker, IdManagerService idManagerService, WriteTransaction t, List<ListenableFuture<Void>> futures) {
+ // Wire Up logic
+ logger.trace( "Wiring between source tunnel end points {}, destination tunnel end points {} " , srcte, dstte );
+ String interfaceName = srcte.getInterfaceName() ;
+ Class<? extends TunnelTypeBase> tunType = srcte.getTunnelType();
+ String tunTypeStr = srcte.getTunnelType().getName();
+ // Form the trunk Interface Name
+ String trunkInterfaceName = ItmUtils.getTrunkInterfaceName( idManagerService, interfaceName,
+ srcte.getIpAddress().getIpv4Address().getValue(),
+ dstte.getIpAddress().getIpv4Address().getValue(),
+ tunTypeStr) ;
+ IpAddress gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
+ IpAddress gwyIpAddress = ( srcte.getSubnetMask().equals(dstte.getSubnetMask()) ) ? gatewayIpObj : srcte.getGwIpAddress() ;
+ logger.debug( " Creating Trunk Interface with parameters trunk I/f Name - {}, parent I/f name - {}, source IP - {}, destination IP - {} gateway IP - {}",trunkInterfaceName, interfaceName, srcte.getIpAddress(), dstte.getIpAddress(), gwyIpAddress ) ;
+ Boolean monitorEnabled = ItmUtils.readMonitoringStateFromDS(dataBroker);
+ Integer monitorInterval = ItmUtils.readMonitorIntervalfromDS(dataBroker);
+ if(monitorInterval == null)
+ monitorInterval = ITMConstants.DEFAULT_MONITOR_INTERVAL;
+ Interface iface = ItmUtils.buildTunnelInterface(srcDpnId, trunkInterfaceName, String.format( "%s %s",ItmUtils.convertTunnelTypetoString(srcte.getTunnelType()), "Trunk Interface"), true, tunType, srcte.getIpAddress(), dstte.getIpAddress(), gwyIpAddress, srcte.getVLANID(), true, monitorEnabled, monitorInterval*1000);
+ logger.debug( " Trunk Interface builder - {} ", iface ) ;
+ InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(trunkInterfaceName);
+ logger.debug( " Trunk Interface Identifier - {} ", trunkIdentifier ) ;
+ logger.trace( " Writing Trunk Interface to Config DS {}, {} ", trunkIdentifier, iface ) ;
+ t.merge(LogicalDatastoreType.CONFIGURATION, trunkIdentifier, iface, true);
+ ItmUtils.itmCache.addInterface(iface);
+ // also update itm-state ds?
+ InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(
+ TunnelList.class)
+ .child(InternalTunnel.class, new InternalTunnelKey( dstDpnId, srcDpnId, tunType));
+ InternalTunnel tnl = ItmUtils.buildInternalTunnel(srcDpnId, dstDpnId, tunType, trunkInterfaceName);
+ //ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, path, tnl, dataBroker, DEFAULT_CALLBACK);
+ t.merge(LogicalDatastoreType.CONFIGURATION,path, tnl, true) ;
+ ItmUtils.itmCache.addInternalTunnel(tnl);
+ return true;
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.itm.confighelpers;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.itm.impl.ItmUtils;
+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.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.DpnEndpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnelKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class ItmInternalTunnelDeleteWorker {
+ private static final Logger logger = LoggerFactory.getLogger(ItmInternalTunnelDeleteWorker.class) ;
+
+ public static List<ListenableFuture<Void>> deleteTunnels(DataBroker dataBroker, IdManagerService idManagerService,IMdsalApiManager mdsalManager,
+ List<DPNTEPsInfo> dpnTepsList, List<DPNTEPsInfo> meshedDpnList)
+ {
+ logger.trace( "TEPs to be deleted {} " , dpnTepsList );
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ try {
+ if (dpnTepsList == null || dpnTepsList.size() == 0) {
+ logger.debug("no vtep to delete");
+ return futures ;
+ }
+
+ if (meshedDpnList == null || meshedDpnList.size() == 0) {
+ logger.debug("No Meshed Vteps");
+ return futures ;
+ }
+ for (DPNTEPsInfo srcDpn : dpnTepsList) {
+ logger.trace("Processing srcDpn " + srcDpn);
+ List<TunnelEndPoints> meshedEndPtCache = new ArrayList<TunnelEndPoints>(ItmUtils.getTEPsForDpn(srcDpn.getDPNID(), meshedDpnList)) ;
+ if(meshedEndPtCache == null ) {
+ logger.debug("No Tunnel End Point configured for this DPN {}", srcDpn.getDPNID());
+ continue ;
+ }
+ logger.debug( "Entries in meshEndPointCache {} ", meshedEndPtCache.size() );
+ for (TunnelEndPoints srcTep : srcDpn.getTunnelEndPoints()) {
+ logger.trace("Processing srcTep " + srcTep);
+ String srcTZone = srcTep.getTransportZone();
+
+ // run through all other DPNS other than srcDpn
+ for (DPNTEPsInfo dstDpn : meshedDpnList) {
+ if (!(srcDpn.getDPNID().equals(dstDpn.getDPNID()))) {
+ for (TunnelEndPoints dstTep : dstDpn.getTunnelEndPoints()) {
+ logger.trace("Processing dstTep " + dstTep);
+ if (dstTep.getTransportZone().equals(srcTZone)) {
+ if( checkIfTrunkExists(dstDpn.getDPNID(), srcDpn.getDPNID(), srcTep.getTunnelType(),dataBroker)) {
+ // remove all trunk interfaces
+ logger.trace("Invoking removeTrunkInterface between source TEP {} , Destination TEP {} " ,srcTep , dstTep);
+ removeTrunkInterface(dataBroker, idManagerService, srcTep, dstTep, srcDpn.getDPNID(), dstDpn.getDPNID(), t, futures);
+ }
+ }
+ }
+ }
+ }
+
+ // removing vtep / dpn from Tunnels OpDs.
+ InstanceIdentifier<TunnelEndPoints> tepPath =
+ InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, srcDpn.getKey())
+ .child(TunnelEndPoints.class, srcTep.getKey()).build();
+
+ logger.trace("Tep Removal of TEP {} from DPNTEPSINFO CONFIG DS with Key {} " + srcTep, srcTep.getKey());
+ t.delete(LogicalDatastoreType.CONFIGURATION, tepPath);
+ // remove the tep from the cache
+ meshedEndPtCache.remove(srcTep) ;
+
+ InstanceIdentifier<DPNTEPsInfo> dpnPath =
+ InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, srcDpn.getKey())
+ .build();
+ /*
+ Optional<DPNTEPsInfo> dpnOptional =
+ ItmUtils.read(LogicalDatastoreType.CONFIGURATION, dpnPath, dataBroker);
+ if (dpnOptional.isPresent()) {
+ */
+ if( meshedEndPtCache.isEmpty()) {
+ //DPNTEPsInfo dpnRead = dpnOptional.get();
+ // remove dpn if no vteps exist on dpn
+ // if (dpnRead.getTunnelEndPoints() == null || dpnRead.getTunnelEndPoints().size() == 0) {
+ logger.debug( "Removing Terminating Service Table Flow ") ;
+ ItmUtils.setUpOrRemoveTerminatingServiceTable(srcDpn.getDPNID(), mdsalManager,false);
+ logger.trace("DPN Removal from DPNTEPSINFO CONFIG DS " + srcDpn.getDPNID());
+ t.delete(LogicalDatastoreType.CONFIGURATION, dpnPath);
+ InstanceIdentifier<DpnEndpoints> tnlContainerPath =
+ InstanceIdentifier.builder(DpnEndpoints.class).build();
+ Optional<DpnEndpoints> containerOptional =
+ ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
+ tnlContainerPath, dataBroker);
+ // remove container if no DPNs are present
+ if (containerOptional.isPresent()) {
+ DpnEndpoints deps = containerOptional.get();
+ if (deps.getDPNTEPsInfo() == null || deps.getDPNTEPsInfo().isEmpty()) {
+ logger.trace("Container Removal from DPNTEPSINFO CONFIG DS");
+ t.delete(LogicalDatastoreType.CONFIGURATION, tnlContainerPath);
+ }
+ }
+ //}
+ }
+ }
+ }
+ futures.add( t.submit() );
+ } catch (Exception e1) {
+ logger.error("exception while deleting tep", e1);
+ }
+ return futures ;
+ }
+
+ private static void removeTrunkInterface(DataBroker dataBroker, IdManagerService idManagerService,
+ TunnelEndPoints srcTep, TunnelEndPoints dstTep, BigInteger srcDpnId, BigInteger dstDpnId,
+ WriteTransaction t, List<ListenableFuture<Void>> futures) {
+ String trunkfwdIfName =
+ ItmUtils.getTrunkInterfaceName( idManagerService, srcTep.getInterfaceName(),
+ srcTep.getIpAddress().getIpv4Address().getValue(),
+ dstTep.getIpAddress().getIpv4Address().getValue(),
+ srcTep.getTunnelType().getName());
+ logger.trace("Removing forward Trunk Interface " + trunkfwdIfName);
+ InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(trunkfwdIfName);
+ logger.debug( " Removing Trunk Interface Name - {} , Id - {} from Config DS ", trunkfwdIfName, trunkIdentifier ) ;
+ t.delete(LogicalDatastoreType.CONFIGURATION, trunkIdentifier);
+ ItmUtils.itmCache.removeInterface(trunkfwdIfName);
+ // also update itm-state ds -- Delete the forward tunnel-interface from the tunnel list
+ InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(
+ TunnelList.class)
+ .child(InternalTunnel.class, new InternalTunnelKey( dstDpnId, srcDpnId, srcTep.getTunnelType()));
+ t.delete(LogicalDatastoreType.CONFIGURATION,path) ;
+ ItmUtils.itmCache.removeInternalTunnel(trunkfwdIfName);
+ // Release the Ids for the forward trunk interface Name
+ ItmUtils.releaseIdForTrunkInterfaceName(idManagerService,srcTep.getInterfaceName(), srcTep.getIpAddress()
+ .getIpv4Address().getValue(), dstTep.getIpAddress().getIpv4Address()
+ .getValue(), srcTep.getTunnelType().getName() );
+
+ String trunkRevIfName =
+ ItmUtils.getTrunkInterfaceName( idManagerService, dstTep.getInterfaceName(),
+ dstTep.getIpAddress().getIpv4Address().getValue(),
+ srcTep.getIpAddress().getIpv4Address().getValue(),
+ srcTep.getTunnelType().getName());
+ logger.trace("Removing Reverse Trunk Interface " + trunkRevIfName);
+ trunkIdentifier = ItmUtils.buildId(trunkRevIfName);
+ logger.debug( " Removing Trunk Interface Name - {} , Id - {} from Config DS ", trunkRevIfName, trunkIdentifier ) ;
+ t.delete(LogicalDatastoreType.CONFIGURATION, trunkIdentifier);
+
+ // also update itm-state ds -- Delete the reverse tunnel-interface from the tunnel list
+ path = InstanceIdentifier.create(
+ TunnelList.class)
+ .child(InternalTunnel.class, new InternalTunnelKey(dstDpnId, srcDpnId, srcTep.getTunnelType()));
+ t.delete(LogicalDatastoreType.CONFIGURATION,path) ;
+
+ // Release the Ids for the reverse trunk interface Name
+ ItmUtils.releaseIdForTrunkInterfaceName(idManagerService, dstTep.getInterfaceName(), dstTep.getIpAddress()
+ .getIpv4Address().getValue(), srcTep.getIpAddress().getIpv4Address()
+ .getValue(),dstTep.getTunnelType().getName());
+ }
+ private static boolean checkIfTrunkExists(BigInteger srcDpnId, BigInteger dstDpnId, Class<? extends TunnelTypeBase> tunType, DataBroker dataBroker) {
+ boolean existsFlag = false ;
+ InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(
+ TunnelList.class)
+ .child(InternalTunnel.class, new InternalTunnelKey( dstDpnId, srcDpnId, tunType));
+ Optional<InternalTunnel> internalTunnels = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,path, dataBroker) ;
+ if( internalTunnels.isPresent())
+ existsFlag = true ;
+ return existsFlag ;
+ }
+}
--- /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.itm.confighelpers;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.itm.impl.ItmUtils;
+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.InterfaceBuilder;
+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.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnelBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+/**
+ * Created by eanraju on 23-Mar-16.
+ */
+public class ItmMonitorIntervalWorker implements Callable<List<ListenableFuture<Void>>> {
+ private static final Logger logger = LoggerFactory.getLogger(ItmMonitorIntervalWorker.class) ;
+ private DataBroker dataBroker;
+ private String tzone;
+ private Integer interval;
+ private List<HwVtep> hwVteps;
+ private Boolean exists;
+
+ public ItmMonitorIntervalWorker(List<HwVtep> hwVteps,String tzone,Integer interval, DataBroker dataBroker, Boolean exists){
+ this.dataBroker = dataBroker;
+ this.tzone = tzone;
+ this.interval = interval;
+ this.hwVteps = hwVteps;
+ this.exists = exists;
+ logger.trace("ItmMonitorToggleWorker initialized with tzone {} and Interval {}",tzone,interval );
+ }
+
+ @Override public List<ListenableFuture<Void>> call() throws Exception {
+ List<ListenableFuture<Void>> futures = new ArrayList<>() ;
+ logger.debug("Invoking Tunnel Monitor Worker tzone = {} Interval= {}",tzone,interval );
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ toggleTunnelMonitoring(hwVteps,interval,tzone,t,exists);
+ futures.add(t.submit());
+ return futures;
+ }
+
+ private void toggleTunnelMonitoring(List<HwVtep> hwVteps,Integer interval, String tzone, WriteTransaction t,Boolean exists) {
+ //exists means hwVteps exist for this tzone
+
+ //List<String> TunnelList = ItmUtils.getTunnelsofTzone(hwVteps, tzone, dataBroker, exists);
+ List<String> TunnelList = ItmUtils.getInternalTunnelsofTzone(tzone,dataBroker);
+ if(TunnelList !=null &&!TunnelList.isEmpty()) {
+ for (String tunnel : TunnelList)
+ toggle(tunnel, interval,t);
+ }
+ }
+
+ private void toggle(String tunnelInterfaceName, Integer interval, WriteTransaction t) {
+ if (tunnelInterfaceName != null) {
+ logger.debug("tunnel {} will have monitor interval {}", tunnelInterfaceName, interval);
+ InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(tunnelInterfaceName);
+ IfTunnel tunnel = new IfTunnelBuilder().setMonitorInterval(interval.longValue() * 1000).build();
+ InterfaceBuilder builder = new InterfaceBuilder().setKey(new InterfaceKey(tunnelInterfaceName))
+ .addAugmentation(IfTunnel.class, tunnel);
+ t.merge(LogicalDatastoreType.CONFIGURATION, trunkIdentifier, builder.build());
+ }
+ }
+}
+
+
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.itm.confighelpers;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.itm.impl.ItmUtils;
+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.InterfaceBuilder;
+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.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.ExternalTunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+/**
+ * Created by eanraju on 23-Mar-16.
+ */
+public class ItmMonitorToggleWorker implements Callable<List<ListenableFuture<Void>>> {
+ private static final Logger logger = LoggerFactory.getLogger(ItmMonitorToggleWorker.class) ;
+ private DataBroker dataBroker;
+ private String tzone;
+ private boolean enabled;
+ private List<HwVtep> hwVteps;
+ private Boolean exists;
+
+ public ItmMonitorToggleWorker(List<HwVtep> hwVteps,String tzone,boolean enabled, DataBroker dataBroker, Boolean exists){
+ this.dataBroker = dataBroker;
+ this.tzone = tzone;
+ this.enabled = enabled;
+ this.hwVteps = hwVteps;
+ this.exists = exists;
+ logger.trace("ItmMonitorToggleWorker initialized with tzone {} and toggleBoolean {}",tzone,enabled );
+ }
+
+ @Override public List<ListenableFuture<Void>> call() throws Exception {
+ List<ListenableFuture<Void>> futures = new ArrayList<>() ;
+ logger.debug("Invoking Tunnel Monitor Worker tzone = {} enabled {}",tzone,enabled );
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ toggleTunnelMonitoring(hwVteps,enabled,tzone,t,exists);
+ futures.add(t.submit());
+ return futures;
+ }
+
+ private void toggleTunnelMonitoring(List<HwVtep> hwVteps,Boolean enabled, String tzone, WriteTransaction t,Boolean exists) {
+ //exists means hwVteps exist for this tzone
+
+ List<String> TunnelList = ItmUtils.getTunnelsofTzone(hwVteps,tzone,dataBroker,exists);
+ if(TunnelList !=null &&!TunnelList.isEmpty()) {
+ for (String tunnel : TunnelList)
+ toggle(tunnel, enabled,t);
+ }
+ }
+
+ private void toggle(String tunnelInterfaceName, boolean enabled, WriteTransaction t) {
+ if(tunnelInterfaceName!=null) {
+ InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(tunnelInterfaceName);
+ IfTunnel tunnel = new IfTunnelBuilder().setMonitorEnabled(enabled).build();
+ InterfaceBuilder builder = new InterfaceBuilder().setKey(new InterfaceKey(tunnelInterfaceName))
+ .addAugmentation(IfTunnel.class, tunnel);
+ t.merge(LogicalDatastoreType.CONFIGURATION, trunkIdentifier, builder.build());
+ }
+ }
+}
+
+
+
+
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.itm.confighelpers;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.vpnservice.itm.impl.ItmUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+
+public class ItmTepAddWorker implements Callable<List<ListenableFuture<Void>>> {
+ private static final Logger logger = LoggerFactory.getLogger(ItmTepAddWorker.class ) ;
+ private DataBroker dataBroker;
+ private IdManagerService idManagerService;
+ private List<DPNTEPsInfo> meshedDpnList;
+ private List<DPNTEPsInfo> cfgdDpnList ;
+ private IMdsalApiManager mdsalManager;
+ private List<HwVtep> cfgdHwVteps;
+
+ public ItmTepAddWorker( List<DPNTEPsInfo> cfgdDpnList, List<HwVtep> hwVtepList, DataBroker broker, IdManagerService idManagerService, IMdsalApiManager mdsalManager) {
+ this.cfgdDpnList = cfgdDpnList ;
+ this.dataBroker = broker ;
+ this.idManagerService = idManagerService;
+ this.mdsalManager = mdsalManager;
+ this.cfgdHwVteps = hwVtepList;
+ logger.trace("ItmTepAddWorker initialized with DpnList {}",cfgdDpnList );
+ logger.trace("ItmTepAddWorker initialized with hwvteplist {}",hwVtepList);
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ List<ListenableFuture<Void>> futures = new ArrayList<>() ;
+ this.meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker) ;
+ logger.debug("Invoking Internal Tunnel build method with Configured DpnList {} ; Meshed DpnList {} ",cfgdDpnList, meshedDpnList );
+ futures.addAll( ItmInternalTunnelAddWorker.build_all_tunnels(dataBroker, idManagerService,mdsalManager, cfgdDpnList, meshedDpnList) ) ;
+ // IF EXTERNAL TUNNELS NEEDS TO BE BUILT, DO IT HERE. IT COULD BE TO DC GATEWAY OR TOR SWITCH
+ //futures.addAll(ItmExternalTunnelAddWorker.buildTunnelsToExternalEndPoint(dataBroker,meshedDpnList, extIp) ;
+ logger.debug("invoking build hwVtepTunnels with hwVteplist {}", cfgdHwVteps );
+ futures.addAll(ItmExternalTunnelAddWorker.buildHwVtepsTunnels(dataBroker, idManagerService,cfgdDpnList,cfgdHwVteps));
+ return futures ;
+ }
+
+ @Override
+ public String toString() {
+ return "ItmTepAddWorker { " +
+ "Configured Dpn List : " + cfgdDpnList +
+ " Meshed Dpn List : " + meshedDpnList + " }" ;
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.itm.confighelpers;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.vpnservice.itm.impl.ItmUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ItmTepRemoveWorker implements Callable<List<ListenableFuture<Void>>> {
+ private static final Logger logger = LoggerFactory.getLogger(ItmTepRemoveWorker.class ) ;
+ private DataBroker dataBroker;
+ private List<DPNTEPsInfo> delDpnList ;
+ private List<DPNTEPsInfo> meshedDpnList ;
+ private IdManagerService idManagerService;
+ private IMdsalApiManager mdsalManager;
+ private List<HwVtep> cfgdHwVteps;
+
+ public ItmTepRemoveWorker( List<DPNTEPsInfo> delDpnList, List<HwVtep> delHwList, DataBroker broker, IdManagerService idManagerService, IMdsalApiManager mdsalManager) {
+ this.delDpnList = delDpnList ;
+ this.dataBroker = broker ;
+ this.idManagerService = idManagerService;
+ this.mdsalManager = mdsalManager;
+ this.cfgdHwVteps = delHwList;
+ logger.trace("ItmTepRemoveWorker initialized with DpnList {}",delDpnList );
+ logger.trace("ItmTepRemoveWorker initialized with cfgdHwTeps {}",delHwList );
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ List<ListenableFuture<Void>> futures = new ArrayList<>() ;
+ this.meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker) ;
+ futures.addAll( ItmInternalTunnelDeleteWorker.deleteTunnels(dataBroker, idManagerService, mdsalManager, delDpnList, meshedDpnList));
+ logger.debug("Invoking Internal Tunnel delete method with DpnList to be deleted {} ; Meshed DpnList {} ",delDpnList, meshedDpnList );
+ // IF EXTERNAL TUNNELS NEEDS TO BE DELETED, DO IT HERE, IT COULD BE TO DC GATEWAY OR TOR SWITCH
+ futures.addAll(ItmExternalTunnelDeleteWorker.deleteHwVtepsTunnels(dataBroker, idManagerService,delDpnList,cfgdHwVteps));
+ return futures ;
+ }
+
+ @Override
+ public String toString() {
+ return "ItmTepRemoveWorker { " +
+ "Delete Dpn List : " + delDpnList + " }" ;
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.itm.impl;
+
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Future;
+
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.apache.commons.net.util.SubnetUtils;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.md.sal.binding.api.NotificationService;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+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.opendaylight.vpnservice.itm.op.rev150701.DpnEndpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan ;
+import org.opendaylight.vpnservice.itm.globals.ITMConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo;
+
+import com.google.common.base.Optional;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.TunnelMonitorEnabled;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.TunnelMonitorInterval;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.TunnelMonitorEnabledBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.TunnelMonitorIntervalBuilder;
+
+public class ITMManager implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(ITMManager.class);
+
+ private final DataBroker broker;
+ private IMdsalApiManager mdsalManager;
+ private NotificationPublishService notificationPublishService;
+
+ List<DPNTEPsInfo> meshedDpnList;
+
+ @Override
+ public void close() throws Exception {
+ LOG.info("ITMManager Closed");
+ }
+
+ public ITMManager(final DataBroker db) {
+ broker = db;
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ public void setNotificationPublishService(NotificationPublishService notificationPublishService) {
+ this.notificationPublishService = notificationPublishService;
+ }
+ protected void initTunnelMonitorDataInConfigDS() {
+ new Thread() {
+ public void run() {
+ boolean readSucceeded = false;
+ InstanceIdentifier<TunnelMonitorEnabled> monitorPath = InstanceIdentifier.builder(TunnelMonitorEnabled.class).build();
+ while (!readSucceeded) {
+ try {
+ Optional<TunnelMonitorEnabled> storedTunnelMonitor = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, monitorPath, broker);
+ // Store default values only when tunnel monitor data is not initialized
+ if (!storedTunnelMonitor.isPresent()) {
+ TunnelMonitorEnabled monitorEnabled =
+ new TunnelMonitorEnabledBuilder().setEnabled(ITMConstants.DEFAULT_MONITOR_ENABLED).build();
+ ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, monitorPath, monitorEnabled, broker, ItmUtils.DEFAULT_CALLBACK);
+
+ InstanceIdentifier<TunnelMonitorInterval> intervalPath = InstanceIdentifier.builder(TunnelMonitorInterval.class).build();
+ TunnelMonitorInterval monitorInteval =
+ new TunnelMonitorIntervalBuilder().setInterval(ITMConstants.DEFAULT_MONITOR_INTERVAL).build();
+ ItmUtils.asyncUpdate(LogicalDatastoreType.CONFIGURATION, intervalPath, monitorInteval, broker, ItmUtils.DEFAULT_CALLBACK);
+ }
+ readSucceeded = true;
+ } catch (Exception e) {
+ LOG.warn("Unable to read monitor enabled info; retrying after some delay");
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ie) {
+ return;
+ }
+ }
+ }
+ }
+ }.start();
+ }
+
+ protected boolean getTunnelMonitorEnabledFromConfigDS() {
+ boolean tunnelMonitorEnabled = true;
+ InstanceIdentifier<TunnelMonitorEnabled> path = InstanceIdentifier.builder(TunnelMonitorEnabled.class).build();
+ Optional<TunnelMonitorEnabled> storedTunnelMonitor = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, broker);
+ if (storedTunnelMonitor.isPresent()) {
+ tunnelMonitorEnabled = storedTunnelMonitor.get().isEnabled();
+ }
+ return tunnelMonitorEnabled;
+ }
+
+ protected int getTunnelMonitorIntervalFromConfigDS() {
+ int tunnelMonitorInterval = ITMConstants.DEFAULT_MONITOR_INTERVAL;
+ InstanceIdentifier<TunnelMonitorInterval> path = InstanceIdentifier.builder(TunnelMonitorInterval.class).build();
+ Optional<TunnelMonitorInterval> storedTunnelMonitor = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, broker);
+ if (storedTunnelMonitor.isPresent()) {
+ tunnelMonitorInterval = storedTunnelMonitor.get().getInterval();
+ }
+ return tunnelMonitorInterval;
+ }
+}
--- /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.itm.impl;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+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.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel;
+
+public class ItmCache {
+ private ConcurrentHashMap<String, Interface> interfaces = null;
+ private ConcurrentHashMap<String, ExternalTunnel> externalTunnels = null;
+ private ConcurrentHashMap<String, InternalTunnel> internalTunnels = null;
+
+ public ItmCache() {
+ this.interfaces = new ConcurrentHashMap<>();
+ this.internalTunnels = new ConcurrentHashMap<>();
+ this.externalTunnels = new ConcurrentHashMap<>();
+ }
+
+ public void addInterface(Interface iface) {
+ this.interfaces.put(iface.getName(), iface);
+ }
+
+ public Interface getInterface(String name) {
+ return this.interfaces.get(name);
+ }
+
+ public Interface removeInterface(String name) {
+ return this.interfaces.remove(name);
+ }
+
+ public Collection<Interface> getAllInterfaces() {
+ return this.interfaces.values();
+ }
+
+ public void addExternalTunnel(ExternalTunnel tunnel) {
+ this.externalTunnels.put(tunnel.getTunnelInterfaceName(), tunnel);
+ }
+
+ public ExternalTunnel getExternalTunnel(String name) {
+ return this.externalTunnels.get(name);
+ }
+
+ public ExternalTunnel removeExternalTunnel(String name) {
+ return this.externalTunnels.remove(name);
+ }
+
+ public void addInternalTunnel(InternalTunnel tunnel) {
+ this.internalTunnels.put(tunnel.getTunnelInterfaceName(), tunnel);
+ }
+
+ public InternalTunnel getInternalTunnel(String name) {
+ return this.internalTunnels.get(name);
+ }
+
+ public InternalTunnel removeInternalTunnel(String name) {
+ return this.internalTunnels.remove(name);
+ }
+
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.itm.impl;
+
+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.binding.api.NotificationPublishService;
+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;
+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.interfaces.IInterfaceManager;
+import org.opendaylight.vpnservice.itm.api.IITMProvider;
+import org.opendaylight.vpnservice.itm.cli.TepCommandHelper;
+import org.opendaylight.vpnservice.itm.globals.ITMConstants;
+import org.opendaylight.vpnservice.itm.listeners.InterfaceStateListener;
+import org.opendaylight.vpnservice.itm.listeners.TransportZoneListener;
+import org.opendaylight.vpnservice.itm.listeners.TunnelMonitorChangeListener;
+import org.opendaylight.vpnservice.itm.listeners.TunnelMonitorIntervalListener;
+import org.opendaylight.vpnservice.itm.listeners.VtepConfigSchemaListener;
+import org.opendaylight.vpnservice.itm.monitoring.ItmTunnelEventListener;
+import org.opendaylight.vpnservice.itm.rpc.ItmManagerRpcService;
+import org.opendaylight.vpnservice.itm.snd.ITMStatusMonitor;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.VtepConfigSchemas;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.VtepConfigSchema;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.VtepConfigSchemaBuilder;
+//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.rev151102.VtepConfigSchemas;
+//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.rev151102.vtep.config.schemas.VtepConfigSchema;
+//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.rev151102.vtep.config.schemas.VtepConfigSchemaBuilder;
+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.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList ;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+public class ItmProvider implements BindingAwareProvider, AutoCloseable, IITMProvider /*,ItmStateService */{
+
+ private static final Logger LOG = LoggerFactory.getLogger(ItmProvider.class);
+ private IInterfaceManager interfaceManager;
+ private ITMManager itmManager;
+ private IMdsalApiManager mdsalManager;
+ private DataBroker dataBroker;
+ private NotificationPublishService notificationPublishService;
+ private ItmManagerRpcService itmRpcService ;
+ private IdManagerService idManager;
+ private NotificationService notificationService;
+ private TepCommandHelper tepCommandHelper;
+ private TransportZoneListener tzChangeListener;
+ private TunnelMonitorChangeListener tnlToggleListener;
+ private TunnelMonitorIntervalListener tnlIntervalListener;
+ private VtepConfigSchemaListener vtepConfigSchemaListener;
+ private InterfaceStateListener ifStateListener;
+ private RpcProviderRegistry rpcProviderRegistry;
+ private static final ITMStatusMonitor itmStatusMonitor = ITMStatusMonitor.getInstance();
+ private ItmTunnelEventListener itmStateListener;
+ static short flag = 0;
+
+ public ItmProvider() {
+ LOG.info("ItmProvider Before register MBean");
+ itmStatusMonitor.registerMbean();
+ }
+
+ public void setRpcProviderRegistry(RpcProviderRegistry rpcProviderRegistry) {
+ this.rpcProviderRegistry = rpcProviderRegistry;
+ }
+
+ public RpcProviderRegistry getRpcProviderRegistry() {
+ return this.rpcProviderRegistry;
+ }
+
+ @Override
+ public void onSessionInitiated(ProviderContext session) {
+ LOG.info("ItmProvider Session Initiated");
+ itmStatusMonitor.reportStatus("STARTING");
+ try {
+ dataBroker = session.getSALService(DataBroker.class);
+ idManager = getRpcProviderRegistry().getRpcService(IdManagerService.class);
+
+ itmManager = new ITMManager(dataBroker);
+ tzChangeListener = new TransportZoneListener(dataBroker, idManager) ;
+ itmRpcService = new ItmManagerRpcService(dataBroker, idManager);
+ vtepConfigSchemaListener = new VtepConfigSchemaListener(dataBroker);
+ this.ifStateListener = new InterfaceStateListener(dataBroker);
+ tnlToggleListener = new TunnelMonitorChangeListener(dataBroker);
+ tnlIntervalListener = new TunnelMonitorIntervalListener(dataBroker);
+ tepCommandHelper = new TepCommandHelper(dataBroker);
+ final BindingAwareBroker.RpcRegistration<ItmRpcService> rpcRegistration = getRpcProviderRegistry().addRpcImplementation(ItmRpcService.class, itmRpcService);
+ itmRpcService.setMdsalManager(mdsalManager);
+ itmManager.setMdsalManager(mdsalManager);
+ itmManager.setNotificationPublishService(notificationPublishService);
+ itmManager.setMdsalManager(mdsalManager);
+ tzChangeListener.setMdsalManager(mdsalManager);
+ tzChangeListener.setItmManager(itmManager);
+ tzChangeListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
+ tnlIntervalListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
+ tnlToggleListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
+ tepCommandHelper = new TepCommandHelper(dataBroker);
+ tepCommandHelper.setInterfaceManager(interfaceManager);
+ itmStateListener =new ItmTunnelEventListener(dataBroker);
+ createIdPool();
+ itmStatusMonitor.reportStatus("OPERATIONAL");
+ } catch (Exception e) {
+ LOG.error("Error initializing services", e);
+ itmStatusMonitor.reportStatus("ERROR");
+ }
+ }
+
+ public void setInterfaceManager(IInterfaceManager interfaceManager) {
+ this.interfaceManager = interfaceManager;
+ }
+
+ public void setNotificationPublishService(NotificationPublishService notificationPublishService) {
+ this.notificationPublishService = notificationPublishService;
+ }
+
+ public void setMdsalApiManager(IMdsalApiManager mdsalMgr) {
+ this.mdsalManager = mdsalMgr;
+ }
+ public void setNotificationService(NotificationService notificationService) {
+ this.notificationService = notificationService;
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (itmManager != null) {
+ itmManager.close();
+ }
+ if (tzChangeListener != null) {
+ tzChangeListener.close();
+ }
+ if (tnlIntervalListener != null) {
+ tnlIntervalListener.close();
+ }
+ if(tnlToggleListener!= null){
+ tnlToggleListener.close();
+ }
+ LOG.info("ItmProvider Closed");
+ }
+
+ private void createIdPool() {
+ CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
+ .setPoolName(ITMConstants.ITM_IDPOOL_NAME)
+ .setLow(ITMConstants.ITM_IDPOOL_START)
+ .setHigh(new BigInteger(ITMConstants.ITM_IDPOOL_SIZE).longValue())
+ .build();
+ try {
+ Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
+ if ((result != null) && (result.get().isSuccessful())) {
+ LOG.debug("Created IdPool for ITM Service");
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Failed to create idPool for ITM Service",e);
+ }
+ }
+
+ @Override
+ public DataBroker getDataBroker() {
+ return dataBroker;
+ }
+ @Override
+ public void createLocalCache(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask,
+ String gatewayIp, String transportZone) {
+ if (tepCommandHelper != null) {
+ tepCommandHelper.createLocalCache(dpnId, portName, vlanId, ipAddress, subnetMask, gatewayIp, transportZone);
+ } else {
+ LOG.trace("tepCommandHelper doesnt exist");
+ }
+ }
+
+ @Override
+ public void commitTeps() {
+ try {
+ tepCommandHelper.deleteOnCommit();
+ tepCommandHelper.buildTeps();
+ } catch (Exception e) {
+ LOG.debug("unable to configure teps" + e.toString());
+ }
+ }
+
+ @Override
+ public void showTeps() {
+ tepCommandHelper.showTeps(itmManager.getTunnelMonitorEnabledFromConfigDS(),
+ itmManager.getTunnelMonitorIntervalFromConfigDS());
+ }
+ public void showState(TunnelList tunnels) {
+ if (tunnels != null)
+ tepCommandHelper.showState(tunnels, itmManager.getTunnelMonitorEnabledFromConfigDS());
+ else
+ LOG.debug("No tunnels available");
+ }
+
+ public void deleteVtep(BigInteger dpnId, String portName, Integer vlanId, String ipAddress, String subnetMask,
+ String gatewayIp, String transportZone) {
+ try {
+ tepCommandHelper.deleteVtep(dpnId, portName, vlanId, ipAddress, subnetMask, gatewayIp, transportZone);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void configureTunnelType(String transportZone, String tunnelType) {
+ LOG .debug("ItmProvider: configureTunnelType {} for transportZone {}", tunnelType, transportZone);
+ tepCommandHelper.configureTunnelType(transportZone,tunnelType);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.vpnservice.itm.api.IITMProvider#addVtepConfigSchema(org.
+ * opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.
+ * rev151102.vtep.config.schemas.VtepConfigSchema)
+ */
+ @Override
+ public void addVtepConfigSchema(VtepConfigSchema vtepConfigSchema) {
+ VtepConfigSchema validatedSchema = ItmUtils.validateForAddVtepConfigSchema(vtepConfigSchema,
+ getAllVtepConfigSchemas());
+
+ String schemaName = validatedSchema.getSchemaName();
+ VtepConfigSchema existingSchema = getVtepConfigSchema(schemaName);
+ if (existingSchema != null) {
+ Preconditions.checkArgument(false, String.format("VtepConfigSchema [%s] already exists!", schemaName));
+ }
+ MDSALUtil.syncWrite(this.dataBroker, LogicalDatastoreType.CONFIGURATION,
+ ItmUtils.getVtepConfigSchemaIdentifier(schemaName), validatedSchema);
+ LOG.debug("Vtep config schema {} added to config DS", schemaName);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.vpnservice.itm.api.IITMProvider#getVtepConfigSchema(java
+ * .lang.String)
+ */
+ @Override
+ public VtepConfigSchema getVtepConfigSchema(String schemaName) {
+ Optional<VtepConfigSchema> schema = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
+ ItmUtils.getVtepConfigSchemaIdentifier(schemaName), this.dataBroker);
+ if (schema.isPresent()) {
+ return schema.get();
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.vpnservice.itm.api.IITMProvider#getAllVtepConfigSchemas(
+ * )
+ */
+ @Override
+ public List<VtepConfigSchema> getAllVtepConfigSchemas() {
+ Optional<VtepConfigSchemas> schemas = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
+ ItmUtils.getVtepConfigSchemasIdentifier(), this.dataBroker);
+ if (schemas.isPresent()) {
+ return schemas.get().getVtepConfigSchema();
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.vpnservice.itm.api.IITMProvider#updateVtepSchema(java.
+ * lang.String, java.util.List, java.util.List)
+ */
+ @Override
+ public void updateVtepSchema(String schemaName, List<BigInteger> lstDpnsForAdd, List<BigInteger> lstDpnsForDelete) {
+ LOG.trace("Updating VTEP schema {} by adding DPN's {} and deleting DPN's {}.", schemaName, lstDpnsForAdd,
+ lstDpnsForDelete);
+
+ VtepConfigSchema schema = ItmUtils.validateForUpdateVtepSchema(schemaName, lstDpnsForAdd, lstDpnsForDelete,
+ this);
+ if (ItmUtils.getDpnIdList(schema.getDpnIds()) == null) {
+ VtepConfigSchemaBuilder builder = new VtepConfigSchemaBuilder(schema);
+ if (ItmUtils.getDpnIdList(schema.getDpnIds()).isEmpty()) {
+ builder.setDpnIds(schema.getDpnIds());
+ schema = builder.build();
+ } else {
+ if (lstDpnsForAdd != null && !lstDpnsForAdd.isEmpty()) {
+ List<BigInteger> originalDpnList = ItmUtils.getDpnIdList(schema.getDpnIds()) ;
+ originalDpnList.addAll(lstDpnsForAdd) ;
+ builder.setDpnIds(ItmUtils.getDpnIdsListFromBigInt(originalDpnList));
+ }
+ if (lstDpnsForDelete != null && !lstDpnsForDelete.isEmpty()) {
+ List<BigInteger> originalDpnList = ItmUtils.getDpnIdList(schema.getDpnIds()) ;
+ originalDpnList.removeAll(lstDpnsForAdd) ;
+ builder.setDpnIds(ItmUtils.getDpnIdsListFromBigInt(originalDpnList)) ;
+ }
+ }
+ schema = builder.build();
+ MDSALUtil.syncWrite(this.dataBroker, LogicalDatastoreType.CONFIGURATION,
+ ItmUtils.getVtepConfigSchemaIdentifier(schemaName), schema);
+ LOG.debug("Vtep config schema {} updated to config DS with DPN's {}", schemaName, ItmUtils.getDpnIdList(schema.getDpnIds()));
+ }
+ }
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.vpnservice.itm.api.IITMProvider#deleteAllVtepSchemas()
+ */
+ @Override
+ public void deleteAllVtepSchemas() {
+ List<VtepConfigSchema> lstSchemas = getAllVtepConfigSchemas();
+ if (lstSchemas != null && !lstSchemas.isEmpty()) {
+ for (VtepConfigSchema schema : lstSchemas) {
+ MDSALUtil.syncDelete(this.dataBroker, LogicalDatastoreType.CONFIGURATION,
+ ItmUtils.getVtepConfigSchemaIdentifier(schema.getSchemaName()));
+ }
+ }
+ LOG.debug("Deleted all Vtep schemas from config DS");
+ }
+
+ public void configureTunnelMonitorEnabled(boolean monitorEnabled) {
+ tepCommandHelper.configureTunnelMonitorEnabled(monitorEnabled);
+ }
+
+ public void configureTunnelMonitorInterval(int interval) {
+ tepCommandHelper.configureTunnelMonitorInterval(interval);
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.itm.impl;
+
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import com.google.common.util.concurrent.CheckedFuture;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.net.util.SubnetUtils;
+import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
+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.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.vpnservice.itm.api.IITMProvider;
+import org.opendaylight.vpnservice.itm.confighelpers.HwVtep;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
+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.iana._if.type.rev140508.Tunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.TunnelMonitorEnabled;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.TunnelMonitorInterval;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.VtepConfigSchemas;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.VtepIpPools;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.VtepConfigSchema;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.VtepConfigSchemaBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.VtepConfigSchemaKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.ip.pools.VtepIpPool;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.ip.pools.VtepIpPoolKey;
+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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.interfaces._interface.NodeIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.interfaces._interface.NodeIdentifierBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.interfaces._interface.NodeIdentifierKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.DpnEndpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.DpnEndpointsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.ExternalTunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfoBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfoKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.dpn.teps.info.TunnelEndPointsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.dpn.teps.info.TunnelEndPointsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnelKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnelKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnels_state.StateTunnelListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.vpnservice.itm.globals.ITMConstants;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+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.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfaceType;
+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.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.vtep.config.schema.DpnIds ;
+//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.itm.rev150701.TransportZones;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZone;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.vtep.config.schema.DpnIdsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.vtep.config.schema.DpnIdsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZoneKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.Vteps;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.ActionType;
+import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
+import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
+import org.opendaylight.vpnservice.mdsalutil.InstructionType;
+import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.net.InetAddresses;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
+public class ItmUtils {
+
+ public static final String DUMMY_IP_ADDRESS = "0.0.0.0";
+ public static final String TUNNEL_TYPE_VXLAN = "VXLAN";
+ public static final String TUNNEL_TYPE_GRE = "GRE";
+ public static final String TUNNEL = "TUNNEL";
+ public static ItmCache itmCache = new ItmCache();
+
+ private static final Logger LOG = LoggerFactory.getLogger(ItmUtils.class);
+
+ public static final FutureCallback<Void> DEFAULT_CALLBACK = new FutureCallback<Void>() {
+ public void onSuccess(Void result) {
+ LOG.debug("Success in Datastore write operation");
+ }
+
+ public void onFailure(Throwable error) {
+ LOG.error("Error in Datastore write operation", error);
+ }
+ };
+
+ public static <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, DataBroker broker) {
+
+ 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 asyncWrite(LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data, DataBroker broker, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.put(datastoreType, path, data, true);
+ Futures.addCallback(tx.submit(), callback);
+ }
+
+ public static <T extends DataObject> void asyncUpdate(LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data, DataBroker broker, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.merge(datastoreType, path, data, true);
+ Futures.addCallback(tx.submit(), callback);
+ }
+
+ public static <T extends DataObject> void asyncDelete(LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, DataBroker broker, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.delete(datastoreType, path);
+ Futures.addCallback(tx.submit(), callback);
+ }
+ public static <T extends DataObject> void asyncBulkRemove(final DataBroker broker,final LogicalDatastoreType datastoreType,
+ List<InstanceIdentifier<T>> pathList, FutureCallback<Void> callback) {
+ if (!pathList.isEmpty()) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ for (InstanceIdentifier<T> path : pathList) {
+ tx.delete(datastoreType, path);
+ }
+ Futures.addCallback(tx.submit(), callback);
+ }
+ }
+
+ public static String getInterfaceName(final BigInteger datapathid, final String portName, final Integer vlanId) {
+ return String.format("%s:%s:%s", datapathid, portName, vlanId);
+ }
+
+ public static BigInteger getDpnIdFromInterfaceName(String interfaceName) {
+ String[] dpnStr = interfaceName.split(":");
+ BigInteger dpnId = new BigInteger(dpnStr[0]);
+ return dpnId;
+ }
+
+ public static String getTrunkInterfaceName(IdManagerService idManager, String parentInterfaceName,
+ String localHostName, String remoteHostName, String tunnelType) {
+ String tunnelTypeStr;
+ if(tunnelType.contains("TunnelTypeGre")) {
+ tunnelTypeStr = ITMConstants.TUNNEL_TYPE_GRE;
+ } else {
+ tunnelTypeStr = ITMConstants.TUNNEL_TYPE_VXLAN;
+ }
+ String trunkInterfaceName = String.format( "%s:%s:%s:%s", parentInterfaceName, localHostName,
+ remoteHostName, tunnelTypeStr);
+ LOG.trace("trunk interface name is {}", trunkInterfaceName);
+ trunkInterfaceName = String.format("%s:%s", TUNNEL, getUniqueId(idManager, trunkInterfaceName));
+ return trunkInterfaceName;
+ }
+
+ public static void releaseIdForTrunkInterfaceName(IdManagerService idManager, String parentInterfaceName, String localHostName, String remoteHostName, String tunnelType) {
+ String tunnelTypeStr;
+ if(tunnelType.contains("TunnelTypeGre")) {
+ tunnelTypeStr = ITMConstants.TUNNEL_TYPE_GRE;
+ } else {
+ tunnelTypeStr = ITMConstants.TUNNEL_TYPE_VXLAN;
+ }
+ String trunkInterfaceName = String.format("%s:%s:%s:%s", parentInterfaceName, localHostName, remoteHostName, tunnelTypeStr);
+ LOG.trace("Releasing Id for trunkInterface - {}", trunkInterfaceName );
+ releaseId(idManager, trunkInterfaceName) ;
+ }
+
+ public static InetAddress getInetAddressFromIpAddress(IpAddress ip) {
+ return InetAddresses.forString(ip.getIpv4Address().getValue());
+ }
+
+ public static InstanceIdentifier<DPNTEPsInfo> getDPNTEPInstance(BigInteger dpIdKey) {
+ InstanceIdentifier.InstanceIdentifierBuilder<DPNTEPsInfo> dpnTepInfoBuilder =
+ InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class,
+ new DPNTEPsInfoKey(dpIdKey));
+ InstanceIdentifier<DPNTEPsInfo> dpnInfo = dpnTepInfoBuilder.build();
+ return dpnInfo;
+ }
+
+ public static DPNTEPsInfo createDPNTepInfo(BigInteger dpId, List<TunnelEndPoints> endpoints) {
+
+ return new DPNTEPsInfoBuilder().setKey(new DPNTEPsInfoKey(dpId)).setTunnelEndPoints(endpoints).build();
+ }
+
+ public static TunnelEndPoints createTunnelEndPoints(BigInteger dpnId, IpAddress ipAddress, String portName, int vlanId,
+ IpPrefix prefix, IpAddress gwAddress, String zoneName, Class<? extends TunnelTypeBase> tunnel_type) {
+ // when Interface Mgr provides support to take in Dpn Id
+ return new TunnelEndPointsBuilder().setKey(new TunnelEndPointsKey(ipAddress, portName,tunnel_type, vlanId))
+ .setSubnetMask(prefix).setGwIpAddress(gwAddress).setTransportZone(zoneName)
+ .setInterfaceName(ItmUtils.getInterfaceName(dpnId, portName, vlanId)).setTunnelType(tunnel_type).build();
+ }
+
+ public static DpnEndpoints createDpnEndpoints(List<DPNTEPsInfo> dpnTepInfo) {
+ return new DpnEndpointsBuilder().setDPNTEPsInfo(dpnTepInfo).build();
+ }
+
+ public static InstanceIdentifier<Interface> buildId(String interfaceName) {
+ InstanceIdentifierBuilder<Interface> idBuilder =
+ InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName));
+ InstanceIdentifier<Interface> id = idBuilder.build();
+ return id;
+ }
+
+ public static Interface buildTunnelInterface(BigInteger dpn, String ifName, String desc, boolean enabled, Class<? extends TunnelTypeBase> tunType,
+ IpAddress localIp, IpAddress remoteIp, IpAddress gatewayIp,Integer vlanId, boolean internal, Boolean monitorEnabled, Integer monitorInterval) {
+ InterfaceBuilder builder = new InterfaceBuilder().setKey(new InterfaceKey(ifName)).setName(ifName)
+ .setDescription(desc).setEnabled(enabled).setType(Tunnel.class);
+ ParentRefs parentRefs = new ParentRefsBuilder().setDatapathNodeIdentifier(dpn).build();
+ builder.addAugmentation(ParentRefs.class, parentRefs);
+ if( vlanId > 0) {
+ IfL2vlan l2vlan = new IfL2vlanBuilder().setVlanId(new VlanId(vlanId)).build();
+ builder.addAugmentation(IfL2vlan.class, l2vlan);
+ }
+ Long monitoringInterval = (long) ITMConstants.DEFAULT_MONITOR_INTERVAL;
+ Boolean monitoringEnabled = true;
+ if(monitorInterval!= null)
+ monitoringInterval = monitorInterval.longValue();
+ if(monitorEnabled!=null )
+ monitoringEnabled = monitorEnabled;
+ IfTunnel tunnel = new IfTunnelBuilder().setTunnelDestination(remoteIp).setTunnelGateway(
+ gatewayIp).setTunnelSource(localIp)
+ .setTunnelInterfaceType(tunType).setInternal(internal).setMonitorEnabled(
+ monitoringEnabled).setMonitorInterval(monitoringInterval).build();
+ builder.addAugmentation(IfTunnel.class, tunnel);
+ return builder.build();
+ }
+
+ public static Interface buildHwTunnelInterface(String tunnelIfName, String desc, boolean enabled, String topo_id,
+ String node_id, Class<? extends TunnelTypeBase> tunType, IpAddress srcIp, IpAddress destIp,
+ IpAddress gWIp, Boolean monitor_enabled, Integer monitor_interval){
+ InterfaceBuilder builder = new InterfaceBuilder().setKey(new InterfaceKey(tunnelIfName)).setName(
+ tunnelIfName).setDescription(desc).
+ setEnabled(enabled).setType(Tunnel.class);
+ List<NodeIdentifier> nodeIds = new ArrayList<NodeIdentifier>();
+ NodeIdentifier hWnode = new NodeIdentifierBuilder().setKey(new NodeIdentifierKey(topo_id)).setTopologyId(
+ topo_id).
+ setNodeId(node_id).build();
+ nodeIds.add(hWnode);
+ ParentRefs parent = new ParentRefsBuilder().setNodeIdentifier(nodeIds).build();
+ builder.addAugmentation(ParentRefs.class , parent);
+ Long monitoringInterval = (long) ITMConstants.DEFAULT_MONITOR_INTERVAL;
+ Boolean monitoringEnabled = true;
+ if(monitor_interval!= null)
+ monitoringInterval = monitor_interval.longValue();
+ if(monitor_enabled!=null )
+ monitoringEnabled = monitor_enabled;
+ IfTunnel tunnel = new IfTunnelBuilder().setTunnelDestination(destIp).setTunnelGateway(gWIp).setTunnelSource(
+ srcIp).setMonitorEnabled(monitoringEnabled).setMonitorInterval(100L).
+ setTunnelInterfaceType(tunType).setInternal(false).build();
+ builder.addAugmentation(IfTunnel.class, tunnel);
+ LOG.trace("iftunnel {} built from hwvtep {} ",tunnel,node_id);
+ return builder.build();
+ }
+
+
+ public static InternalTunnel buildInternalTunnel( BigInteger srcDpnId, BigInteger dstDpnId,
+ Class<? extends TunnelTypeBase> tunType,
+ String trunkInterfaceName) {
+ InternalTunnel tnl = new InternalTunnelBuilder().setKey(new InternalTunnelKey(dstDpnId, srcDpnId, tunType)).setDestinationDPN(dstDpnId)
+ .setSourceDPN(srcDpnId).setTransportType(tunType)
+ .setTunnelInterfaceName(trunkInterfaceName).build();
+ return tnl ;
+ }
+
+ public static ExternalTunnel buildExternalTunnel(String srcNode, String dstNode,
+ Class<? extends TunnelTypeBase> tunType,
+ String trunkInterfaceName) {
+ ExternalTunnel extTnl = new ExternalTunnelBuilder().setKey(
+ new ExternalTunnelKey(dstNode, srcNode, tunType))
+ .setSourceDevice(srcNode).setDestinationDevice(dstNode)
+ .setTunnelInterfaceName(trunkInterfaceName)
+ .setTransportType(tunType).build();
+ return extTnl ;
+ }
+
+ public static List<DPNTEPsInfo> getTunnelMeshInfo(DataBroker dataBroker) {
+ List<DPNTEPsInfo> dpnTEPs= null ;
+
+ // Read the EndPoint Info from the operational database
+ InstanceIdentifierBuilder<DpnEndpoints> depBuilder = InstanceIdentifier.builder( DpnEndpoints.class) ;
+ InstanceIdentifier<DpnEndpoints> deps = depBuilder.build();
+ Optional<DpnEndpoints> dpnEps = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, deps, dataBroker);
+ if (dpnEps.isPresent()) {
+ DpnEndpoints tn= dpnEps.get() ;
+ dpnTEPs = tn.getDPNTEPsInfo();
+ LOG.debug( "Read from CONFIGURATION datastore - No. of Dpns " , dpnTEPs.size() );
+ }else
+ LOG.debug( "No Dpn information in CONFIGURATION datastore " );
+ return dpnTEPs ;
+ }
+
+ public static int getUniqueId(IdManagerService idManager, String idKey) {
+ AllocateIdInput getIdInput = new AllocateIdInputBuilder()
+ .setPoolName(ITMConstants.ITM_IDPOOL_NAME)
+ .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 {
+ LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when getting Unique Id",e);
+ }
+ return 0;
+ }
+
+ public static void releaseId(IdManagerService idManager, String idKey) {
+ ReleaseIdInput idInput =
+ new ReleaseIdInputBuilder().setPoolName(ITMConstants.ITM_IDPOOL_NAME).setIdKey(idKey).build();
+ try {
+ Future<RpcResult<Void>> result = idManager.releaseId(idInput);
+ RpcResult<Void> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when getting Unique Id for key {}", idKey, e);
+ }
+ }
+
+ public static List<DPNTEPsInfo> getDPNTEPListFromDPNId(DataBroker dataBroker, List<BigInteger> dpnIds) {
+ List<DPNTEPsInfo> meshedDpnList = getTunnelMeshInfo(dataBroker) ;
+ List<DPNTEPsInfo> cfgDpnList = new ArrayList<DPNTEPsInfo>();
+ if( null != meshedDpnList) {
+ for(BigInteger dpnId : dpnIds) {
+ for( DPNTEPsInfo teps : meshedDpnList ) {
+ if( dpnId.equals(teps.getDPNID()))
+ cfgDpnList.add( teps) ;
+ }
+ }
+ }
+ return cfgDpnList;
+ }
+
+ public static void setUpOrRemoveTerminatingServiceTable(BigInteger dpnId, IMdsalApiManager mdsalManager, boolean addFlag) {
+ String logmsg = ( addFlag == true) ? "Installing" : "Removing";
+ LOG.trace( logmsg + " PUNT to Controller flow in DPN {} ", dpnId );
+ long dpId;
+ List<ActionInfo> listActionInfo = new ArrayList<ActionInfo>();
+ listActionInfo.add(new ActionInfo(ActionType.punt_to_controller,
+ new String[] {}));
+
+ try {
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+
+ mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {
+ BigInteger.valueOf(ITMConstants.LLDP_SERVICE_ID) }));
+
+ List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
+ mkInstructions.add(new InstructionInfo(InstructionType.apply_actions,
+ listActionInfo));
+
+ FlowEntity terminatingServiceTableFlowEntity = MDSALUtil
+ .buildFlowEntity(
+ dpnId,
+ NwConstants.INTERNAL_TUNNEL_TABLE,
+ getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE,
+ ITMConstants.LLDP_SERVICE_ID), 5, String.format("%s:%d","ITM Flow Entry ",ITMConstants.LLDP_SERVICE_ID),
+ 0, 0, ITMConstants.COOKIE_ITM
+ .add(BigInteger.valueOf(ITMConstants.LLDP_SERVICE_ID)),
+ mkMatches, mkInstructions);
+ if(addFlag)
+ mdsalManager.installFlow(terminatingServiceTableFlowEntity);
+ else
+ mdsalManager.removeFlow(terminatingServiceTableFlowEntity);
+ } catch (Exception e) {
+ LOG.error("Error while setting up Table 36 for {}", dpnId, e);
+ }
+ }
+
+ private static String getFlowRef(long termSvcTable, int svcId) {
+ return new StringBuffer().append(termSvcTable).append(svcId).toString();
+ }
+ public static InstanceIdentifier<VtepConfigSchema> getVtepConfigSchemaIdentifier(String schemaName) {
+ return InstanceIdentifier.builder(VtepConfigSchemas.class)
+ .child(VtepConfigSchema.class, new VtepConfigSchemaKey(schemaName)).build();
+ }
+
+ public static InstanceIdentifier<VtepConfigSchema> getVtepConfigSchemaIdentifier() {
+ return InstanceIdentifier.builder(VtepConfigSchemas.class).child(VtepConfigSchema.class).build();
+ }
+ public static InstanceIdentifier<VtepConfigSchemas> getVtepConfigSchemasIdentifier() {
+ return InstanceIdentifier.builder(VtepConfigSchemas.class).build();
+ }
+ public static InstanceIdentifier<VtepIpPool> getVtepIpPoolIdentifier(String subnetCidr) {
+ return InstanceIdentifier.builder(VtepIpPools.class).child(VtepIpPool.class, new VtepIpPoolKey(subnetCidr))
+ .build();
+ }
+ public static VtepConfigSchema validateForAddVtepConfigSchema(VtepConfigSchema schema,
+ List<VtepConfigSchema> existingSchemas) {
+ VtepConfigSchema validSchema = validateVtepConfigSchema(schema);
+ for (VtepConfigSchema existingSchema : emptyIfNull(existingSchemas)) {
+ if (!StringUtils.equalsIgnoreCase(schema.getSchemaName(), existingSchema.getSchemaName())
+ && schema.getSubnet().equals(existingSchema.getSubnet())) {
+ String subnetCidr = getSubnetCidrAsString(schema.getSubnet());
+ Preconditions.checkArgument(false, new StringBuilder("VTEP schema with subnet [").append(subnetCidr)
+ .append("] already exists. Multiple VTEP schemas with same subnet is not allowed.").toString());
+ }
+ }
+ if (isNotEmpty(getDpnIdList(validSchema.getDpnIds()))) {
+ String tzone = validSchema.getTransportZoneName();
+ List<BigInteger> lstDpns = getConflictingDpnsAlreadyConfiguredWithTz(validSchema.getSchemaName(), tzone,
+ getDpnIdList(validSchema.getDpnIds()), existingSchemas);
+ if (!lstDpns.isEmpty()) {
+ Preconditions.checkArgument(false,
+ new StringBuilder("DPN's ").append(lstDpns).append(" already configured for transport zone ")
+ .append(tzone).append(". Only one end point per transport Zone per Dpn is allowed.")
+ .toString());
+ }
+ if (schema.getTunnelType().equals(TunnelTypeGre.class)){
+ validateForSingleGreTep(validSchema.getSchemaName(), getDpnIdList(validSchema.getDpnIds()), existingSchemas);
+ }
+ }
+ return validSchema;
+ }
+ private static void validateForSingleGreTep(String schemaName, List<BigInteger> lstDpnsForAdd,
+ List<VtepConfigSchema> existingSchemas) {
+ for (VtepConfigSchema existingSchema : emptyIfNull(existingSchemas)) {
+ if ((TunnelTypeGre.class).equals(existingSchema.getTunnelType())
+ && !StringUtils.equalsIgnoreCase(schemaName, existingSchema.getSchemaName())) {
+ List<BigInteger> lstConflictingDpns = new ArrayList<>(getDpnIdList(existingSchema.getDpnIds()));
+ lstConflictingDpns.retainAll(emptyIfNull(lstDpnsForAdd));
+ if (!lstConflictingDpns.isEmpty()) {
+ String errMsg = new StringBuilder("DPN's ").append(lstConflictingDpns)
+ .append(" already configured with GRE TEP. Mutiple GRE TEP's on a single DPN are not allowed.")
+ .toString();
+ Preconditions.checkArgument(false, errMsg);
+ }
+ }
+ }
+ }
+ public static VtepConfigSchema validateVtepConfigSchema(VtepConfigSchema schema) {
+ Preconditions.checkNotNull(schema);
+ Preconditions.checkArgument(StringUtils.isNotBlank(schema.getSchemaName()));
+ Preconditions.checkArgument(StringUtils.isNotBlank(schema.getPortName()));
+ Preconditions.checkArgument((schema.getVlanId() >= 0 && schema.getVlanId() < 4095),
+ "Invalid VLAN ID, range (0-4094)");
+ Preconditions.checkArgument(StringUtils.isNotBlank(schema.getTransportZoneName()));
+ Preconditions.checkNotNull(schema.getSubnet());
+ String subnetCidr = getSubnetCidrAsString(schema.getSubnet());
+ SubnetUtils subnetUtils = new SubnetUtils(subnetCidr);
+ IpAddress gatewayIp = schema.getGatewayIp();
+ if (gatewayIp != null) {
+ String strGatewayIp = String.valueOf(gatewayIp.getValue());
+ if (!strGatewayIp.equals(ITMConstants.DUMMY_IP_ADDRESS) && !subnetUtils.getInfo().isInRange(strGatewayIp)) {
+ Preconditions.checkArgument(false, new StringBuilder("Gateway IP address ").append(strGatewayIp)
+ .append(" is not in subnet range ").append(subnetCidr).toString());
+ }
+ }
+ ItmUtils.getExcludeIpAddresses(schema.getExcludeIpFilter(), subnetUtils.getInfo());
+ return new VtepConfigSchemaBuilder(schema).setTunnelType(schema.getTunnelType()).build();
+ }
+ public static String validateTunnelType(String tunnelType) {
+ if (tunnelType == null) {
+ tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN;
+ } else {
+ tunnelType = StringUtils.upperCase(tunnelType);
+ String error = new StringBuilder("Invalid tunnel type. Valid values: ")
+ .append(ITMConstants.TUNNEL_TYPE_VXLAN).append(" | ").append(ITMConstants.TUNNEL_TYPE_GRE)
+ .toString();
+ Preconditions.checkArgument(ITMConstants.TUNNEL_TYPE_VXLAN.equals(tunnelType)
+ || ITMConstants.TUNNEL_TYPE_GRE.equals(tunnelType), error);
+ }
+ return tunnelType;
+ }
+ private static List<BigInteger> getConflictingDpnsAlreadyConfiguredWithTz(String schemaName, String tzone,
+ List<BigInteger> lstDpns, List<VtepConfigSchema> existingSchemas) {
+ List<BigInteger> lstConflictingDpns = new ArrayList<>();
+ for (VtepConfigSchema schema : emptyIfNull(existingSchemas)) {
+ if (!StringUtils.equalsIgnoreCase(schemaName, schema.getSchemaName())
+ && StringUtils.equals(schema.getTransportZoneName(), tzone)) {
+ lstConflictingDpns = new ArrayList<>(getDpnIdList(schema.getDpnIds()));
+ lstConflictingDpns.retainAll(lstDpns);
+ if (!lstConflictingDpns.isEmpty()) {
+ break;
+ }
+ }
+ }
+ return lstConflictingDpns;
+ }
+ public static VtepConfigSchema constructVtepConfigSchema(String schemaName, String portName, Integer vlanId,
+ String subnetMask, String gatewayIp, String transportZone,String tunnelType, List<BigInteger> dpnIds,
+ String excludeIpFilter) {
+ IpAddress gatewayIpObj = StringUtils.isBlank(gatewayIp) ? null : new IpAddress(gatewayIp.toCharArray());
+ IpPrefix subnet = StringUtils.isBlank(subnetMask) ? null : new IpPrefix(subnetMask.toCharArray());
+ Class<? extends TunnelTypeBase> tunType ;
+ if( tunnelType.equals(ITMConstants.TUNNEL_TYPE_VXLAN))
+ tunType = TunnelTypeVxlan.class ;
+ else
+ tunType = TunnelTypeGre.class ;
+ VtepConfigSchemaBuilder schemaBuilder = new VtepConfigSchemaBuilder().setSchemaName(schemaName)
+ .setPortName(portName).setVlanId(vlanId).setSubnet(subnet).setGatewayIp(gatewayIpObj)
+ .setTransportZoneName(transportZone).setTunnelType(tunType).setDpnIds(getDpnIdsListFromBigInt(dpnIds))
+ .setExcludeIpFilter(excludeIpFilter);
+ return schemaBuilder.build();
+ }
+ public static List<IpAddress> getExcludeIpAddresses(String excludeIpFilter, SubnetInfo subnetInfo) {
+ final List<IpAddress> lstIpAddress = new ArrayList<>();
+ if (StringUtils.isBlank(excludeIpFilter)) {
+ return lstIpAddress;
+ }
+ final String[] arrIps = StringUtils.split(excludeIpFilter, ',');
+ for (String ip : arrIps) {
+ if (StringUtils.countMatches(ip, "-") == 1) {
+ final String[] arrIpRange = StringUtils.split(ip, '-');
+ String strStartIp = StringUtils.trim(arrIpRange[0]);
+ String strEndIp = StringUtils.trim(arrIpRange[1]);
+ Preconditions.checkArgument(InetAddresses.isInetAddress(strStartIp),
+ new StringBuilder("Invalid exclude IP filter: invalid IP address value ").append(strStartIp)
+ .toString());
+ Preconditions.checkArgument(InetAddresses.isInetAddress(strEndIp),
+ new StringBuilder("Invalid exclude IP filter: invalid IP address value ").append(strEndIp)
+ .toString());
+ Preconditions.checkArgument(subnetInfo.isInRange(strStartIp),
+ new StringBuilder("Invalid exclude IP filter: IP address [").append(strStartIp)
+ .append("] not in subnet range ").append(subnetInfo.getCidrSignature()).toString());
+ Preconditions.checkArgument(subnetInfo.isInRange(strEndIp),
+ new StringBuilder("Invalid exclude IP filter: IP address [").append(strEndIp)
+ .append("] not in subnet range ").append(subnetInfo.getCidrSignature()).toString());
+ int startIp = subnetInfo.asInteger(strStartIp);
+ int endIp = subnetInfo.asInteger(strEndIp);
+
+ Preconditions.checkArgument(startIp < endIp,
+ new StringBuilder("Invalid exclude IP filter: Invalid range [").append(ip).append("] ")
+ .toString());
+ for (int i = startIp; i <= endIp; i++) {
+ String ipAddress = ipFormat(toIpArray(i));
+ validateAndAddIpAddressToList(subnetInfo, lstIpAddress, ipAddress);
+ }
+ } else {
+ validateAndAddIpAddressToList(subnetInfo, lstIpAddress, ip);
+ }
+ }
+ return lstIpAddress;
+ }
+ private static void validateAndAddIpAddressToList(SubnetInfo subnetInfo, final List<IpAddress> lstIpAddress,
+ String ipAddress) {
+ String ip = StringUtils.trim(ipAddress);
+ Preconditions.checkArgument(InetAddresses.isInetAddress(ip),
+ new StringBuilder("Invalid exclude IP filter: invalid IP address value ").append(ip).toString());
+ Preconditions.checkArgument(subnetInfo.isInRange(ip),
+ new StringBuilder("Invalid exclude IP filter: IP address [").append(ip).append("] not in subnet range ")
+ .append(subnetInfo.getCidrSignature()).toString());
+ lstIpAddress.add(new IpAddress(ip.toCharArray()));
+ }
+ private static int[] toIpArray(int val) {
+ int[] ret = new int[4];
+ for (int j = 3; j >= 0; --j) {
+ ret[j] |= ((val >>> 8 * (3 - j)) & (0xff));
+ }
+ return ret;
+ }
+ private static String ipFormat(int[] octets) {
+ StringBuilder str = new StringBuilder();
+ for (int i = 0; i < octets.length; ++i) {
+ str.append(octets[i]);
+ if (i != octets.length - 1) {
+ str.append(".");
+ }
+ }
+ return str.toString();
+ }
+ public static VtepConfigSchema validateForUpdateVtepSchema(String schemaName, List<BigInteger> lstDpnsForAdd,
+ List<BigInteger> lstDpnsForDelete, IITMProvider itmProvider) {
+ Preconditions.checkArgument(StringUtils.isNotBlank(schemaName));
+ if ((lstDpnsForAdd == null || lstDpnsForAdd.isEmpty())
+ && (lstDpnsForDelete == null || lstDpnsForDelete.isEmpty())) {
+ Preconditions.checkArgument(false,
+ new StringBuilder("DPN ID list for add | delete is null or empty in schema ").append(schemaName)
+ .toString());
+ }
+ VtepConfigSchema schema = itmProvider.getVtepConfigSchema(schemaName);
+ if (schema == null) {
+ Preconditions.checkArgument(false, new StringBuilder("Specified VTEP Schema [").append(schemaName)
+ .append("] doesn't exists!").toString());
+ }
+ List<BigInteger> existingDpnIds = getDpnIdList(schema.getDpnIds());
+ if (isNotEmpty(lstDpnsForAdd)) {
+ if (isNotEmpty(existingDpnIds)) {
+ List<BigInteger> lstAlreadyExistingDpns = new ArrayList<>(existingDpnIds);
+ lstAlreadyExistingDpns.retainAll(lstDpnsForAdd);
+ Preconditions.checkArgument(lstAlreadyExistingDpns.isEmpty(),
+ new StringBuilder("DPN ID's ").append(lstAlreadyExistingDpns)
+ .append(" already exists in VTEP schema [").append(schemaName).append("]").toString());
+ }
+ if (schema.getTunnelType().equals(TunnelTypeGre.class)) {
+ validateForSingleGreTep(schema.getSchemaName(), lstDpnsForAdd, itmProvider.getAllVtepConfigSchemas());
+ }
+ }
+ if (isNotEmpty(lstDpnsForDelete)) {
+ if (existingDpnIds == null || existingDpnIds.isEmpty()) {
+ StringBuilder builder = new StringBuilder("DPN ID's ").append(lstDpnsForDelete)
+ .append(" specified for delete from VTEP schema [").append(schemaName)
+ .append("] are not configured in the schema.");
+ Preconditions.checkArgument(false, builder.toString());
+ } else if (!existingDpnIds.containsAll(lstDpnsForDelete)) {
+ List<BigInteger> lstConflictingDpns = new ArrayList<>(lstDpnsForDelete);
+ lstConflictingDpns.removeAll(existingDpnIds);
+ StringBuilder builder = new StringBuilder("DPN ID's ").append(lstConflictingDpns)
+ .append(" specified for delete from VTEP schema [").append(schemaName)
+ .append("] are not configured in the schema.");
+ Preconditions.checkArgument(false, builder.toString());
+ }
+ }
+ return schema;
+ }
+ public static String getSubnetCidrAsString(IpPrefix subnet) {
+ return (subnet == null) ? StringUtils.EMPTY : String.valueOf(subnet.getValue());
+ }
+ public static <T> List<T> emptyIfNull(List<T> list) {
+ return (list == null) ? Collections.<T> emptyList() : list;
+ }
+ public static <T> boolean isEmpty(Collection<T> collection) {
+ return (collection == null || collection.isEmpty()) ? true : false;
+ }
+ public static <T> boolean isNotEmpty(Collection<T> collection) {
+ return !isEmpty(collection);
+ }
+ public static HwVtep createHwVtepObject(String topo_id, String node_id, IpAddress ipAddress, IpPrefix ipPrefix, IpAddress gatewayIP, int vlanID, Class<? extends TunnelTypeBase> tunnel_type, TransportZone transportZone) {
+ HwVtep hwVtep = new HwVtep();
+ hwVtep.setGatewayIP(gatewayIP);
+ hwVtep.setHwIp(ipAddress);
+ hwVtep.setIpPrefix(ipPrefix);
+ hwVtep.setNode_id(node_id);
+ hwVtep.setTopo_id(topo_id);
+ hwVtep.setTransportZone(transportZone.getZoneName());
+ hwVtep.setTunnel_type(tunnel_type);
+ hwVtep.setVlanID(vlanID);
+ return hwVtep;
+ }
+
+ public static String getHwParentIf(String topo_id, String srcNodeid) {
+ return String.format("%s:%s", topo_id, srcNodeid);
+ }
+
+ public static <T extends DataObject> void syncWrite(LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data, DataBroker broker) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.put(datastoreType, path, data, true);
+ CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+ try {
+ futures.get();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("ITMUtils:SyncWrite , Error writing to datastore (path, data) : ({}, {})", path, data);
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+
+ public static List<BigInteger> getDpnIdList( List<DpnIds> dpnIds ) {
+ List<BigInteger> dpnList = new ArrayList<BigInteger>() ;
+ for( DpnIds dpn : dpnIds) {
+ dpnList.add(dpn.getDPN()) ;
+ }
+ return dpnList ;
+ }
+
+ public static List<DpnIds> getDpnIdsListFromBigInt( List<BigInteger> dpnIds) {
+ List<DpnIds> dpnIdList = new ArrayList<DpnIds>() ;
+ DpnIdsBuilder builder = new DpnIdsBuilder() ;
+ for( BigInteger dpnId : dpnIds) {
+ dpnIdList.add(builder.setKey(new DpnIdsKey(dpnId)).setDPN(dpnId).build() );
+ }
+ return dpnIdList;
+ }
+
+ public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> buildStateInterfaceId(String interfaceName) {
+ InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> idBuilder =
+ InstanceIdentifier.builder(InterfacesState.class)
+ .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class,
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(
+ interfaceName));
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> id = idBuilder.build();
+ return id;
+}
+ public static Boolean readMonitoringStateFromDS(DataBroker dataBroker) {
+ InstanceIdentifier<TunnelMonitorEnabled> iid = InstanceIdentifier.create(TunnelMonitorEnabled.class);
+ Optional<TunnelMonitorEnabled> tunnelMonitorEnabledOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
+ iid, dataBroker);
+ if(tunnelMonitorEnabledOptional.isPresent())
+ return tunnelMonitorEnabledOptional.get().isEnabled();
+ return null;
+ }
+
+ public static Integer readMonitorIntervalfromDS(DataBroker dataBroker) {
+ InstanceIdentifier<TunnelMonitorInterval> iid = InstanceIdentifier.create(TunnelMonitorInterval.class);
+ Optional<TunnelMonitorInterval> tunnelMonitorIOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, iid, dataBroker);
+ if(tunnelMonitorIOptional.isPresent())
+ return tunnelMonitorIOptional.get().getInterval();
+ return null;
+ }
+ public static List<String> getTunnelsofTzone(List<HwVtep> hwVteps, String tzone, DataBroker dataBroker, Boolean hwVtepsExist) {
+ List<String> tunnels = new ArrayList<String>();
+ InstanceIdentifier<TransportZone> path = InstanceIdentifier.builder(TransportZones.class).
+ child(TransportZone.class, new TransportZoneKey(tzone)).build();
+ Optional<TransportZone> tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
+ Class<? extends TunnelTypeBase> tunType = tZoneOptional.get().getTunnelType();
+ if (tZoneOptional.isPresent()) {
+ if (tZoneOptional.get().getSubnets() != null && !tZoneOptional.get().getSubnets().isEmpty()) {
+ for (Subnets sub : tZoneOptional.get().getSubnets()) {
+ if (sub.getVteps() != null && !sub.getVteps().isEmpty()) {
+ for (Vteps vtepLocal : sub.getVteps()) {
+ for (Vteps vtepRemote : sub.getVteps()) {
+ if (!vtepLocal.equals(vtepRemote)) {
+ InternalTunnelKey key = new InternalTunnelKey(vtepRemote.getDpnId(), vtepLocal.getDpnId(), tunType);
+ InstanceIdentifier<InternalTunnel> intIID =
+ InstanceIdentifier.builder(TunnelList.class).
+ child(InternalTunnel.class, key).build();
+ Optional<InternalTunnel> TunnelsOptional =
+ ItmUtils.read(LogicalDatastoreType.CONFIGURATION, intIID, dataBroker);
+ if (TunnelsOptional.isPresent()) {
+ LOG.trace("Internal Tunnel added {}",TunnelsOptional.get().getTunnelInterfaceName());
+ tunnels.add(TunnelsOptional.get().getTunnelInterfaceName());
+ }
+ }
+ }
+ if(hwVteps!= null && !hwVteps.isEmpty()) {
+ for (HwVtep hwVtep : hwVteps) {
+ tunnels.add(getExtTunnel(hwVtep.getNode_id(), vtepLocal.getDpnId().toString(),
+ tunType, dataBroker));
+ tunnels.add(getExtTunnel(vtepLocal.getDpnId().toString(), hwVtep.getNode_id(),
+ tunType, dataBroker));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (hwVtepsExist) {
+ for (HwVtep hwVtep : hwVteps) {
+ for (HwVtep hwVtepOther : hwVteps) {
+ if (!hwVtep.getHwIp().equals(hwVtepOther.getHwIp())) {
+ tunnels.add(getExtTunnel(hwVtep.getNode_id(), hwVtepOther.getNode_id(), tunType, dataBroker));
+ tunnels.add(getExtTunnel(hwVtepOther.getNode_id(), hwVtep.getNode_id(), tunType, dataBroker));
+ }
+ }
+ }
+ }
+ return tunnels;
+ }
+ public static List<String> getInternalTunnelsofTzone(String tzone, DataBroker dataBroker) {
+ List<String> tunnels = new ArrayList<String>();
+ LOG.trace("Getting internal tunnels of {}",tzone);
+ InstanceIdentifier<TransportZone> path = InstanceIdentifier.builder(TransportZones.class).
+ child(TransportZone.class, new TransportZoneKey(tzone)).build();
+ Optional<TransportZone> tZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
+ if (tZoneOptional.isPresent()) {
+ if (tZoneOptional.get().getSubnets() != null && !tZoneOptional.get().getSubnets().isEmpty()) {
+ for (Subnets sub : tZoneOptional.get().getSubnets()) {
+ if (sub.getVteps() != null && !sub.getVteps().isEmpty()) {
+ for (Vteps vtepLocal : sub.getVteps()) {
+ for (Vteps vtepRemote : sub.getVteps()) {
+ if (!vtepLocal.equals(vtepRemote)) {
+ InternalTunnelKey key = new InternalTunnelKey(vtepRemote.getDpnId(), vtepLocal.getDpnId(), tZoneOptional.get().getTunnelType());
+ InstanceIdentifier<InternalTunnel> intIID =
+ InstanceIdentifier.builder(TunnelList.class).
+ child(InternalTunnel.class, key).build();
+ Optional<InternalTunnel> TunnelsOptional =
+ ItmUtils.read(LogicalDatastoreType.CONFIGURATION, intIID, dataBroker);
+ if (TunnelsOptional.isPresent()) {
+ LOG.trace("Internal Tunnel added {}",
+ TunnelsOptional.get().getTunnelInterfaceName());
+ tunnels.add(TunnelsOptional.get().getTunnelInterfaceName());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return tunnels;
+ }
+ private static String getExtTunnel(String node_id, String dpId,Class<? extends TunnelTypeBase> tunType, DataBroker dataBroker) {
+ LOG.trace("getting ext tunnel for {} and dpId {}",node_id,dpId);
+ ExternalTunnelKey key = getExternalTunnelKey(dpId,node_id, tunType);
+ InstanceIdentifier<ExternalTunnel> intIID = InstanceIdentifier.builder(ExternalTunnelList.class).
+ child(ExternalTunnel.class, key).build();
+ Optional<ExternalTunnel> TunnelsOptional =
+ ItmUtils.read(LogicalDatastoreType.CONFIGURATION, intIID, dataBroker);
+ if (TunnelsOptional.isPresent()) {
+ LOG.trace("ext tunnel returned {} ",TunnelsOptional.get().getTunnelInterfaceName());
+ return TunnelsOptional.get().getTunnelInterfaceName();
+ }
+ return null;
+ }
+ public static ExternalTunnelKey getExternalTunnelKey(String dst , String src, Class<? extends TunnelTypeBase> tunType) {
+ if (src.indexOf("physicalswitch") > 0) {
+ src = src.substring(0, src.indexOf("physicalswitch") - 1);
+ }
+ if (dst.indexOf("physicalswitch") > 0) {
+ dst = dst.substring(0, dst.indexOf("physicalswitch") - 1);
+ }
+ return new ExternalTunnelKey(dst, src, tunType);
+ }
+ public static List<TunnelEndPoints> getTEPsForDpn( BigInteger srcDpn, List<DPNTEPsInfo> dpnList) {
+ for (DPNTEPsInfo dpn : dpnList) {
+ if( dpn.getDPNID().equals(srcDpn)) {
+ return dpn.getTunnelEndPoints() ;
+ }
+ }
+ return null ;
+ }
+ public static TunnelList getAllInternalTunnels(DataBroker broker) {
+ InstanceIdentifier<TunnelList> tunnelListInstanceIdentifier = InstanceIdentifier.builder(TunnelList.class).build();
+ Optional<TunnelList> tunnelList = read(LogicalDatastoreType.CONFIGURATION, tunnelListInstanceIdentifier, broker);
+ if (tunnelList.isPresent()) {
+ return tunnelList.get();
+ }
+ return null;
+ }
+ public static InternalTunnel getInternalTunnel(String interfaceName, DataBroker broker) {
+ InternalTunnel internalTunnel = null;
+ TunnelList tunnelList = getAllInternalTunnels(broker);
+ if (tunnelList != null && tunnelList.getInternalTunnel() != null) {
+ List<InternalTunnel> internalTunnels = tunnelList.getInternalTunnel();
+ for (InternalTunnel tunnel : internalTunnels) {
+ if (tunnel.getTunnelInterfaceName().equalsIgnoreCase(interfaceName)) {
+ internalTunnel = tunnel;
+ break;
+ }
+ }
+ }
+ return internalTunnel;
+ }
+ public static ExternalTunnel getExternalTunnel(String interfaceName, DataBroker broker) {
+ ExternalTunnel externalTunnel = null;
+ List<ExternalTunnel> externalTunnels = getAllExternalTunnels(broker);
+ for (ExternalTunnel tunnel : externalTunnels) {
+ if (StringUtils.equalsIgnoreCase(interfaceName, tunnel.getTunnelInterfaceName())) {
+ externalTunnel = tunnel;
+ break;
+ }
+ }
+ return externalTunnel;
+ }
+ public static List<ExternalTunnel> getAllExternalTunnels(DataBroker broker) {
+ List<ExternalTunnel> result = null;
+ InstanceIdentifier<ExternalTunnelList> id = InstanceIdentifier.builder(ExternalTunnelList.class).build();
+ Optional<ExternalTunnelList> tunnelList = read(LogicalDatastoreType.CONFIGURATION, id, broker);
+ if (tunnelList.isPresent()) {
+ result = tunnelList.get().getExternalTunnel();
+ }
+ if (result == null) {
+ result = Collections.emptyList();
+ }
+ return result;
+ }
+ public static String convertTunnelTypetoString(Class<? extends TunnelTypeBase> tunType ) {
+ String tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN;
+ if( tunType.equals(TunnelTypeVxlan.class))
+ tunnelType = ITMConstants.TUNNEL_TYPE_VXLAN ;
+ else if( tunType.equals(TunnelTypeGre.class) )
+ tunnelType = ITMConstants.TUNNEL_TYPE_GRE ;
+ else if (tunnelType.equals(TunnelTypeMplsOverGre.class))
+ tunnelType = ITMConstants.TUNNEL_TYPE_MPLS_OVER_GRE;
+ return tunnelType ;
+ }
+ public static boolean isItmIfType(Class<? extends InterfaceType> ifType) {
+ if( (ifType != null) && (ifType.isAssignableFrom(Tunnel.class)) ) {
+ return true;
+ }
+ return false;
+ }
+ public static StateTunnelListKey getTunnelStateKey( org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface iface) {
+ StateTunnelListKey key = null;
+ if(isItmIfType(iface.getType())) {
+ key = new StateTunnelListKey(iface.getName());
+ }
+ return key;
+ }
+ public static void updateTunnelsCache(DataBroker broker) {
+ List<InternalTunnel> internalTunnels = getAllInternalTunnels(broker, LogicalDatastoreType.CONFIGURATION);
+ for (InternalTunnel tunnel : internalTunnels) {
+ itmCache.addInternalTunnel(tunnel);
+ }
+ List<ExternalTunnel> externalTunnels = getAllExternalTunnels(broker, LogicalDatastoreType.CONFIGURATION);
+ for (ExternalTunnel tunnel : externalTunnels) {
+ itmCache.addExternalTunnel(tunnel);
+ }
+ }
+ public static List<ExternalTunnel> getAllExternalTunnels(DataBroker dataBroker, LogicalDatastoreType datastoreType) {
+ List<ExternalTunnel> result = null;
+ InstanceIdentifier<ExternalTunnelList> iid = InstanceIdentifier.builder(ExternalTunnelList.class).build();
+ Optional<ExternalTunnelList> tunnelList = read(LogicalDatastoreType.CONFIGURATION, iid, dataBroker);
+ if (tunnelList.isPresent()) {
+ result = tunnelList.get().getExternalTunnel();
+ }
+ if (result == null) {
+ result = Collections.emptyList();
+ }
+ return result;
+ }
+ public static List<InternalTunnel> getAllInternalTunnels(DataBroker dataBroker, LogicalDatastoreType datastoreType) {
+ List<InternalTunnel> result = null;
+ InstanceIdentifier<TunnelList> iid = InstanceIdentifier.builder(TunnelList.class).build();
+ Optional<TunnelList> tunnelList = read(LogicalDatastoreType.CONFIGURATION, iid, dataBroker);
+ if (tunnelList.isPresent()) {
+ result = tunnelList.get().getInternalTunnel();
+ }
+ if (result == null) {
+ result = Collections.emptyList();
+ }
+ return result;
+ }
+ public static Interface getInterface(
+ String name, DataBroker broker) {
+ Interface result = itmCache.getInterface(name);
+ if (result == null) {
+ InstanceIdentifier<Interface> iid =
+ InstanceIdentifier.builder(Interfaces.class)
+ .child(Interface.class, new InterfaceKey(name)).build();
+ Optional<Interface> optInterface = read(LogicalDatastoreType.CONFIGURATION, iid, broker);
+ if (optInterface.isPresent()) {
+ result = optInterface.get();
+ itmCache.addInterface(result);
+ }
+ }
+ return result;
+ }
+}
--- /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.itm.listeners;
+
+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.itm.impl.ItmUtils;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+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.state.Interface;
+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.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TepTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TepTypeExternal;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TepTypeHwvtep;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TepTypeInternal;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelsState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnels_state.StateTunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnels_state.StateTunnelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnels_state.StateTunnelListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnels_state.state.tunnel.list.DstInfoBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnels_state.state.tunnel.list.SrcInfoBuilder;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.net.InetAddresses;
+
+public class InterfaceStateListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+
+ public InterfaceStateListener(final DataBroker db) {
+ super(Interface.class);
+ broker = db;
+ registerListener(db);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up interface state listener", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("Interface state listener Closed");
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), InterfaceStateListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("ITM Interfaces State listener registration fail!", e);
+ throw new IllegalStateException("ITM Interfaces State listener registration failed.", e);
+ }
+ }
+
+ private InstanceIdentifier<Interface> getWildCardPath() {
+ return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Interface> identifier, Interface iface) {
+ LOG.trace("Interface added: {}", iface);
+ if(ItmUtils.isItmIfType(iface.getType())) {
+ LOG.debug("Interface of type Tunnel added: {}", iface.getName());
+ updateItmState(iface);
+ }
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Interface> identifier,
+ Interface iface) {
+ LOG.trace("Interface deleted: {}", iface);
+ if(ItmUtils.isItmIfType(iface.getType())) {
+ LOG.debug("Tunnel interface deleted: {}", iface.getName());
+ StateTunnelListKey tlKey = null;
+ tlKey = ItmUtils.getTunnelStateKey(iface);
+ InstanceIdentifier<StateTunnelList> stListId = buildStateTunnelListId(tlKey);
+ LOG.trace("Deleting tunnel_state for Id: {}", stListId);
+ ItmUtils.asyncDelete(LogicalDatastoreType.OPERATIONAL, stListId, broker, ItmUtils.DEFAULT_CALLBACK);
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Interface> identifier,
+ Interface original, Interface update) {
+ /*
+ * update contains only delta, may not include iftype
+ * Note: This assumes type can't be edited on the fly
+ */
+ if(ItmUtils.isItmIfType(original.getType())) {
+ LOG.trace("Interface updated. Old: {} New: {}", original, update);
+ OperStatus operStatus = update.getOperStatus();
+ if( operStatus != null ) {
+ LOG.debug("Tunnel Interface {} changed state to {}", original.getName(), operStatus);
+ updateItmState(update);
+ }
+ }
+ }
+
+ private void updateItmState(Interface iface) {
+ StateTunnelListKey tlKey = null;
+ tlKey = ItmUtils.getTunnelStateKey(iface);
+ LOG.trace("TunnelStateKey: {} for interface: {}", tlKey, iface.getName());
+ InstanceIdentifier<StateTunnelList> stListId = buildStateTunnelListId(tlKey);
+ Optional<StateTunnelList> tunnelsState = ItmUtils.read(LogicalDatastoreType.OPERATIONAL, stListId, broker);
+ StateTunnelList tunnelStateList;
+ StateTunnelListBuilder stlBuilder;
+ boolean tunnelState = (iface.getOperStatus().equals(OperStatus.Up)) ? (true):(false);
+ if(tunnelsState.isPresent()) {
+ tunnelStateList = tunnelsState.get();
+ stlBuilder = new StateTunnelListBuilder(tunnelStateList);
+ stlBuilder.setTunnelState(tunnelState);
+ StateTunnelList stList = stlBuilder.build();
+ LOG.trace("Updating tunnel_state: {} for Id: {}",stList, stListId);
+ ItmUtils.asyncUpdate(LogicalDatastoreType.OPERATIONAL, stListId, stList, broker, ItmUtils.DEFAULT_CALLBACK);
+ } else {
+ // Create new Tunnel State
+ try {
+ /*FIXME:
+ * A defensive try-catch to find issues without disrupting existing behavior.
+ */
+ tunnelStateList = buildStateTunnelList(tlKey, iface.getName(), tunnelState);
+ LOG.trace("Creating tunnel_state: {} for Id: {}", tunnelStateList, stListId);
+ ItmUtils.asyncUpdate(LogicalDatastoreType.OPERATIONAL, stListId, tunnelStateList, broker,
+ ItmUtils.DEFAULT_CALLBACK);
+ } catch (Exception e) {
+ LOG.warn("Exception trying to create tunnel state for {}", iface.getName(), e);
+ }
+ }
+ }
+
+ private StateTunnelList buildStateTunnelList(StateTunnelListKey tlKey, String name, boolean state) {
+ StateTunnelListBuilder stlBuilder = new StateTunnelListBuilder();
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
+ ItmUtils.getInterface(name, broker);
+ IfTunnel ifTunnel = iface.getAugmentation(IfTunnel.class);
+ ParentRefs parentRefs = iface.getAugmentation(ParentRefs.class);
+ if(ifTunnel == null && parentRefs == null) {
+ return null;
+ }
+ DstInfoBuilder dstInfoBuilder = new DstInfoBuilder();
+ SrcInfoBuilder srcInfoBuilder = new SrcInfoBuilder();
+ dstInfoBuilder.setTepIp(ifTunnel.getTunnelDestination());
+ srcInfoBuilder.setTepIp(ifTunnel.getTunnelSource());
+ //TODO: Add/Improve logic for device type
+ InternalTunnel internalTunnel = ItmUtils.itmCache.getInternalTunnel(name);
+ ExternalTunnel externalTunnel = ItmUtils.itmCache.getExternalTunnel(name);
+ if(internalTunnel == null && externalTunnel == null) {
+ // both not present in cache. let us update and try again.
+ ItmUtils.updateTunnelsCache(broker);
+ internalTunnel = ItmUtils.itmCache.getInternalTunnel(name);
+ externalTunnel = ItmUtils.itmCache.getExternalTunnel(name);
+ }
+ if(internalTunnel != null) {
+ srcInfoBuilder.setTepDeviceId(internalTunnel.getSourceDPN().toString()).setTepDeviceType(TepTypeInternal.class);
+ dstInfoBuilder.setTepDeviceId(internalTunnel.getDestinationDPN().toString())
+ .setTepDeviceType(TepTypeInternal.class);
+ stlBuilder.setTransportType(internalTunnel.getTransportType());
+ } else if(externalTunnel != null) {
+ ExternalTunnel tunnel = ItmUtils.itmCache.getExternalTunnel(name);
+ srcInfoBuilder.setTepDeviceId(tunnel.getSourceDevice())
+ .setTepDeviceType(getDeviceType(tunnel.getSourceDevice()));
+ dstInfoBuilder.setTepDeviceId(tunnel.getDestinationDevice())
+ .setTepDeviceType(getDeviceType(tunnel.getSourceDevice()))
+ .setTepIp(ifTunnel.getTunnelDestination());
+ stlBuilder.setTransportType(tunnel.getTransportType());
+ }
+ stlBuilder.setKey(tlKey).setTunnelInterfaceName(name).setTunnelState(state)
+ .setDstInfo(dstInfoBuilder.build()).setSrcInfo(srcInfoBuilder.build());
+ return stlBuilder.build();
+ }
+
+ private Class<? extends TepTypeBase> getDeviceType(String device) {
+ if(device.startsWith("hwvtep")) {
+ return TepTypeHwvtep.class;
+ } else if(InetAddresses.isInetAddress(device)) {
+ return TepTypeExternal.class;
+ } else {
+ return TepTypeInternal.class;
+ }
+ }
+
+ private InstanceIdentifier<StateTunnelList> buildStateTunnelListId(StateTunnelListKey tlKey) {
+ InstanceIdentifier<StateTunnelList> stListId =
+ InstanceIdentifier.builder(TunnelsState.class).child(StateTunnelList.class, tlKey).build();
+ return stListId;
+ }
+
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.vpnservice.itm.listeners;
+
+import java.math.BigInteger;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.vpnservice.itm.confighelpers.HwVtep;
+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.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZonesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZone;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.DeviceVteps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.Vteps;
+import org.opendaylight.vpnservice.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.vpnservice.itm.impl.ITMManager;
+import org.opendaylight.vpnservice.itm.impl.ItmUtils;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.vpnservice.itm.confighelpers.ItmTepAddWorker ;
+import org.opendaylight.vpnservice.itm.confighelpers.ItmTepRemoveWorker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class listens for interface creation/removal/update in Configuration DS.
+ * This is used to handle interfaces for base of-ports.
+ */
+public class TransportZoneListener extends AsyncDataTreeChangeListenerBase<TransportZone, TransportZoneListener> implements AutoCloseable{
+ private static final Logger LOG = LoggerFactory.getLogger(TransportZoneListener.class);
+ private DataBroker dataBroker;
+ private IdManagerService idManagerService;
+ private IMdsalApiManager mdsalManager;
+ private ITMManager itmManager;
+
+ public TransportZoneListener(final DataBroker dataBroker, final IdManagerService idManagerService) {
+ super(TransportZone.class, TransportZoneListener.class);
+ this.dataBroker = dataBroker;
+ this.idManagerService = idManagerService;
+ initializeTZNode(dataBroker);
+ }
+
+ public void setItmManager(ITMManager itmManager) {
+ this.itmManager = itmManager;
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ private void initializeTZNode(DataBroker db) {
+ ReadWriteTransaction transaction = db.newReadWriteTransaction();
+ InstanceIdentifier<TransportZones> path = InstanceIdentifier.create(TransportZones.class);
+ CheckedFuture<Optional<TransportZones>, ReadFailedException> tzones =
+ transaction.read(LogicalDatastoreType.CONFIGURATION,path);
+ try {
+ if (!tzones.get().isPresent()) {
+ TransportZonesBuilder tzb = new TransportZonesBuilder();
+ transaction.put(LogicalDatastoreType.CONFIGURATION,path,tzb.build());
+ transaction.submit();
+ } else {
+ transaction.cancel();
+ }
+ } catch (Exception e) {
+ LOG.error("Error initializing TransportZones {}",e);
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ LOG.info("tzChangeListener Closed");
+ }
+ @Override
+ protected InstanceIdentifier<TransportZone> getWildCardPath() {
+ return InstanceIdentifier.create(TransportZones.class).child(TransportZone.class);
+ }
+
+ @Override
+ protected TransportZoneListener getDataTreeChangeListener() {
+ return TransportZoneListener.this;
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<TransportZone> key, TransportZone tzOld) {
+ LOG.debug("Received Transport Zone Remove Event: {}, {}", key, tzOld);
+ List<DPNTEPsInfo> opDpnList = createDPNTepInfo(tzOld);
+ List<HwVtep> hwVtepList = createhWVteps(tzOld);
+ LOG.trace("Delete: Invoking deleteTunnels in ItmManager with DpnList {}", opDpnList);
+ if(opDpnList.size()>0 || hwVtepList.size()>0) {
+ LOG.trace("Delete: Invoking ItmManager");
+ LOG.trace("Delete: Invoking ItmManager with hwVtep List {} " , hwVtepList);
+ // itmManager.deleteTunnels(opDpnList);
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ ItmTepRemoveWorker removeWorker = new ItmTepRemoveWorker(opDpnList,hwVtepList, dataBroker, idManagerService, mdsalManager);
+ coordinator.enqueueJob(tzOld.getZoneName(), removeWorker);
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<TransportZone> key, TransportZone tzOld, TransportZone tzNew) {
+ LOG.debug("Received Transport Zone Update Event: Key - {}, Old - {}, Updated - {}", key, tzOld, tzNew);
+ //if( !(tzOld.equals(tzNew))) {
+ //add(key, tzNew);
+ List<DPNTEPsInfo> oldDpnTepsList = new ArrayList<DPNTEPsInfo>();
+ oldDpnTepsList = createDPNTepInfo(tzOld);
+ List<DPNTEPsInfo> newDpnTepsList = new ArrayList<DPNTEPsInfo>();
+ newDpnTepsList = createDPNTepInfo(tzNew);
+ List<DPNTEPsInfo> oldDpnTepsListcopy = new ArrayList<DPNTEPsInfo>();
+ oldDpnTepsListcopy.addAll(oldDpnTepsList);
+ LOG.trace("oldcopy0" + oldDpnTepsListcopy);
+ List<DPNTEPsInfo> newDpnTepsListcopy = new ArrayList<DPNTEPsInfo>();
+ newDpnTepsListcopy.addAll(newDpnTepsList);
+ LOG.trace("newcopy0" + newDpnTepsListcopy);
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+
+ oldDpnTepsList.removeAll(newDpnTepsListcopy);
+ newDpnTepsList.removeAll(oldDpnTepsListcopy);
+
+ LOG.trace("oldDpnTepsList" + oldDpnTepsList);
+ LOG.trace("newDpnTepsList" + newDpnTepsList);
+ LOG.trace("oldcopy"+oldDpnTepsListcopy);
+ LOG.trace("newcopy"+newDpnTepsListcopy);
+ LOG.trace("oldcopy Size "+oldDpnTepsList.size());
+ LOG.trace("newcopy Size "+newDpnTepsList.size());
+ if(newDpnTepsList.size() > 0) {
+ LOG.trace( "Adding TEPs " );
+ ItmTepAddWorker addWorker = new ItmTepAddWorker(newDpnTepsList, Collections.<HwVtep>emptyList(), dataBroker, idManagerService, mdsalManager);
+ coordinator.enqueueJob(tzNew.getZoneName(), addWorker);
+ }
+ if(oldDpnTepsList.size() > 0) {
+ LOG.trace( "Removing TEPs " );
+ ItmTepRemoveWorker removeWorker =
+ new ItmTepRemoveWorker(oldDpnTepsList, Collections.<HwVtep>emptyList(), dataBroker, idManagerService, mdsalManager);
+ coordinator.enqueueJob(tzNew.getZoneName(), removeWorker);
+ }
+ List<HwVtep> oldHwList = new ArrayList<HwVtep>();
+ oldHwList = createhWVteps(tzOld);
+ List<HwVtep> newHwList = new ArrayList<HwVtep>();
+ newHwList = createhWVteps(tzNew);
+ List<HwVtep> oldHwListcopy = new ArrayList<HwVtep>();
+ oldHwListcopy.addAll(oldHwList);
+ LOG.trace("oldHwListcopy0" + oldHwListcopy);
+ List<HwVtep> newHwListcopy = new ArrayList<HwVtep>();
+ newHwListcopy.addAll(newHwList);
+ LOG.trace("newHwListcopy0" + newHwListcopy);
+
+ oldHwList.removeAll(newHwListcopy);
+ newHwList.removeAll(oldHwListcopy);
+ LOG.trace("oldHwList" + oldHwList);
+ LOG.trace("newHwList" + newHwList);
+ LOG.trace("oldHwListcopy" + oldHwListcopy);
+ LOG.trace("newHwListcopy" + newHwListcopy);
+ if(newHwList.size() > 0) {
+ LOG.trace( "Adding HW TEPs " );
+ ItmTepAddWorker addWorker = new ItmTepAddWorker(Collections.<DPNTEPsInfo>emptyList(), newHwList, dataBroker, idManagerService, mdsalManager);
+ coordinator.enqueueJob(tzNew.getZoneName(), addWorker);
+ }
+ if(oldHwList.size() > 0) {
+ LOG.trace( "Removing HW TEPs " );
+ ItmTepRemoveWorker removeWorker =
+ new ItmTepRemoveWorker(Collections.<DPNTEPsInfo>emptyList(), oldHwList, dataBroker,
+ idManagerService, mdsalManager);
+ coordinator.enqueueJob(tzNew.getZoneName(), removeWorker);
+ }
+
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<TransportZone> key, TransportZone tzNew) {
+ LOG.debug("Received Transport Zone Add Event: {}, {}", key, tzNew);
+ List<DPNTEPsInfo> opDpnList = createDPNTepInfo(tzNew);
+ List<HwVtep> hwVtepList = createhWVteps(tzNew);
+ LOG.trace("Add: Operational dpnTepInfo - Before invoking ItmManager {}", opDpnList);
+ if(opDpnList.size()>0 || hwVtepList.size()>0) {
+ LOG.trace("Add: Invoking ItmManager with DPN List {} " , opDpnList);
+ LOG.trace("Add: Invoking ItmManager with hwVtep List {} " , hwVtepList);
+ //itmManager.build_all_tunnels(opDpnList);
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ ItmTepAddWorker addWorker = new ItmTepAddWorker(opDpnList, hwVtepList, dataBroker, idManagerService, mdsalManager);
+ coordinator.enqueueJob(tzNew.getZoneName(), addWorker);
+ }
+ }
+
+ private List<DPNTEPsInfo> createDPNTepInfo(TransportZone transportZone){
+
+ Map<BigInteger, List<TunnelEndPoints>> mapDPNToTunnelEndpt = new ConcurrentHashMap<>();
+ List<DPNTEPsInfo> dpnTepInfo = new ArrayList<DPNTEPsInfo>();
+ // List<TransportZone> transportZoneList = transportZones.getTransportZone();
+ // for(TransportZone transportZone : transportZoneList) {
+ String zone_name = transportZone.getZoneName();
+ Class<? extends TunnelTypeBase> tunnel_type = transportZone.getTunnelType();
+ LOG.trace("Transport Zone_name: {}", zone_name);
+ List<Subnets> subnetsList = transportZone.getSubnets();
+ if(subnetsList!=null){
+ for (Subnets subnet : subnetsList) {
+ IpPrefix ipPrefix = subnet.getPrefix();
+ IpAddress gatewayIP = subnet.getGatewayIp();
+ int vlanID = subnet.getVlanId();
+ LOG.trace("IpPrefix: {}, gatewayIP: {}, vlanID: {} ", ipPrefix, gatewayIP, vlanID);
+ List<Vteps> vtepsList = subnet.getVteps();
+ if(vtepsList!=null && !vtepsList.isEmpty()) {
+ for (Vteps vteps : vtepsList) {
+ BigInteger dpnID = vteps.getDpnId();
+ String port = vteps.getPortname();
+ IpAddress ipAddress = vteps.getIpAddress();
+ LOG.trace("DpnID: {}, port: {}, ipAddress: {}", dpnID, port, ipAddress);
+ TunnelEndPoints tunnelEndPoints =
+ ItmUtils.createTunnelEndPoints(dpnID, ipAddress, port, vlanID, ipPrefix,
+ gatewayIP, zone_name, tunnel_type);
+ List<TunnelEndPoints> tunnelEndPointsList = mapDPNToTunnelEndpt.get(dpnID);
+ if (tunnelEndPointsList != null) {
+ LOG.trace("Existing DPN info list in the Map: {} ", dpnID);
+ tunnelEndPointsList.add(tunnelEndPoints);
+ } else {
+ LOG.trace("Adding new DPN info list to the Map: {} ", dpnID);
+ tunnelEndPointsList = new ArrayList<TunnelEndPoints>();
+ tunnelEndPointsList.add(tunnelEndPoints);
+ mapDPNToTunnelEndpt.put(dpnID, tunnelEndPointsList);
+ }
+ }
+ }
+ }
+ }
+ //}
+ if(mapDPNToTunnelEndpt.size()>0){
+ Set<BigInteger> keys = mapDPNToTunnelEndpt.keySet();
+ LOG.trace("List of dpns in the Map: {} ", keys);
+ for(BigInteger key: keys){
+ DPNTEPsInfo newDpnTepsInfo = ItmUtils.createDPNTepInfo(key, mapDPNToTunnelEndpt.get(key));
+ dpnTepInfo.add(newDpnTepsInfo);
+ }
+ }
+ return dpnTepInfo;
+ }
+ private List<HwVtep> createhWVteps(TransportZone transportZone) {
+ //creating hwVtepsList to pass
+ //Inventory model would deprecate Eventually, so not creating hWvtepslist under createDpnTepInfo();
+ List<HwVtep> hwVtepsList = new ArrayList<HwVtep>();
+ //currently the list has only one object always since we are adding L2Gws one by one and only to One TransportZone.
+ //Map<BigInteger, List<TunnelEndPoints>> mapDPNToTunnelEndpt = new ConcurrentHashMap<>();
+
+ String zone_name = transportZone.getZoneName();
+ Class<? extends TunnelTypeBase> tunnel_type = transportZone.getTunnelType();
+ LOG.trace("Transport Zone_name: {}", zone_name);
+ List<Subnets> subnetsList = transportZone.getSubnets();
+ if (subnetsList != null) {
+ for (Subnets subnet : subnetsList) {
+ IpPrefix ipPrefix = subnet.getPrefix();
+ IpAddress gatewayIP = subnet.getGatewayIp();
+ int vlanID = subnet.getVlanId();
+ LOG.trace("IpPrefix: {}, gatewayIP: {}, vlanID: {} ", ipPrefix, gatewayIP, vlanID);
+ List<DeviceVteps> deviceVtepsList = subnet.getDeviceVteps();
+ if (deviceVtepsList != null) {
+ for (DeviceVteps vteps : deviceVtepsList) {
+ String topo_id = vteps.getTopologyId();
+ String node_id = vteps.getNodeId();
+ IpAddress ipAddress = vteps.getIpAddress();
+ LOG.trace("topo-id: {}, node-id: {}, ipAddress: {}", topo_id, node_id, ipAddress);
+ //TunnelEndPoints tunnelEndPoints = ItmUtils.createTunnelEndPoints(dpnID, ipAddress, port, vlanID, ipPrefix, gatewayIP, zone_name, tunnel_type);
+ HwVtep hwVtep = ItmUtils.createHwVtepObject(topo_id, node_id, ipAddress, ipPrefix, gatewayIP, vlanID, tunnel_type, transportZone);
+
+ if (hwVtepsList != null) {
+ LOG.trace("Existing hwVteps");
+ hwVtepsList.add(hwVtep);
+ } else {
+ LOG.trace("Adding new HwVtep {} info ", hwVtep.getHwIp());
+ hwVtepsList.add(hwVtep);
+ }
+ }
+ }
+ }
+ }
+ LOG.trace("returning hwvteplist {}", hwVtepsList);
+ return hwVtepsList;
+ }
+}
--- /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.itm.listeners;
+
+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.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.vpnservice.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
+import org.opendaylight.vpnservice.itm.confighelpers.HwVtep;
+import org.opendaylight.vpnservice.itm.confighelpers.ItmMonitorToggleWorker;
+import org.opendaylight.vpnservice.itm.confighelpers.ItmTepAddWorker;
+import org.opendaylight.vpnservice.itm.globals.ITMConstants;
+import org.opendaylight.vpnservice.itm.impl.ItmUtils;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+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.InterfaceBuilder;
+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.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.ExternalTunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZone;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.DeviceVteps;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TunnelMonitorChangeListener extends AsyncDataTreeChangeListenerBase<TunnelMonitorEnabled, TunnelMonitorChangeListener>
+ implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(TunnelMonitorChangeListener.class);
+ private final DataBroker broker;
+ // private final IInterfaceManager interfaceManager;
+
+ public TunnelMonitorChangeListener(final DataBroker db) {
+ super(TunnelMonitorEnabled.class, TunnelMonitorChangeListener.class);
+ broker = db;
+ // interfaceManager = ifManager;
+ // registerListener(db);
+ }
+
+ /* private void registerListener(final DataBroker db) {
+ try {
+ TunnelMonitorChangeListener monitorEnabledChangeListener = new TunnelMonitorChangeListener();
+ monitorEnabledListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ monitorEnabledChangeListener.getWildCardPath(), monitorEnabledChangeListener, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("ITM Monitor Interfaces DataChange listener registration fail!", e);
+ throw new IllegalStateException("ITM Monitor registration Listener failed.", e);
+ }
+ }
+*/ @Override
+ public void close() throws Exception {
+ /* if (monitorEnabledListenerRegistration != null) {
+ try {
+ monitorEnabledListenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ monitorEnabledListenerRegistration = null;
+ }
+
+ if (monitorIntervalListenerRegistration != null) {
+ try {
+ monitorIntervalListenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ monitorIntervalListenerRegistration = null;
+ }
+*/
+ LOG.info("Tunnel Monitor listeners Closed");
+ }
+
+ @Override protected InstanceIdentifier<TunnelMonitorEnabled> getWildCardPath() {
+ return InstanceIdentifier.create(TunnelMonitorEnabled.class);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<TunnelMonitorEnabled> key, TunnelMonitorEnabled dataObjectModification) {
+ List<HwVtep> hwVteps = new ArrayList<HwVtep>();
+ Boolean hwVtepsExist = false;
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ InstanceIdentifier<TransportZones> path = InstanceIdentifier.builder(TransportZones.class).build();
+ Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, broker);
+ if (tZonesOptional.isPresent()) {
+ TransportZones tZones = tZonesOptional.get();
+ for (TransportZone tzone : tZones.getTransportZone()) {
+ hwVtepsExist = false;
+ hwVteps = new ArrayList<HwVtep>();
+ if (tzone.getSubnets() != null && !tzone.getSubnets().isEmpty()) {
+ for (Subnets sub : tzone.getSubnets()) {
+ if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) {
+ hwVtepsExist = true;
+ for (DeviceVteps deviceVtep : sub.getDeviceVteps()) {
+ HwVtep hwVtep = ItmUtils.createHwVtepObject(deviceVtep.getTopologyId(), deviceVtep.getNodeId(),
+ deviceVtep.getIpAddress(), sub.getPrefix(), sub.getGatewayIp(), sub.getVlanId(),
+ tzone.getTunnelType(), tzone);
+ hwVteps.add(hwVtep);
+ }
+ }
+ }
+ }
+ LOG.debug("Remove:Calling TunnelMonitorToggleWorker with tzone = {} and {}",tzone.getZoneName(),dataObjectModification.isEnabled());
+ ItmMonitorToggleWorker toggleWorker = new ItmMonitorToggleWorker(hwVteps, tzone.getZoneName(),
+ false, broker, hwVtepsExist);
+ coordinator.enqueueJob(tzone.getZoneName(), toggleWorker);
+ }
+ }
+ }
+
+
+ @Override protected void update(InstanceIdentifier<TunnelMonitorEnabled> key,
+ TunnelMonitorEnabled dataObjectModificationBefore,
+ TunnelMonitorEnabled dataObjectModificationAfter) {
+ LOG.debug("update TunnelMonitorChangeListener called with {}",dataObjectModificationAfter.isEnabled());
+ List<HwVtep> hwVteps = new ArrayList<HwVtep>();
+ Boolean hwVtepsExist = false;
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ InstanceIdentifier<TransportZones> path = InstanceIdentifier.builder(TransportZones.class).build();
+ Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, broker);
+ if (tZonesOptional.isPresent()) {
+ TransportZones tZones = tZonesOptional.get();
+ for (TransportZone tzone : tZones.getTransportZone()) {
+ hwVtepsExist = false;
+ hwVteps = new ArrayList<HwVtep>();
+ if (tzone.getSubnets() != null && !tzone.getSubnets().isEmpty()) {
+ for (Subnets sub : tzone.getSubnets()) {
+ if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) {
+ hwVtepsExist = true;//gets set to true only if this particular tzone has
+ LOG.debug("Update:Calling TunnelMonitorToggleWorker with tzone = {} and hwtepExist",tzone.getZoneName());
+ for (DeviceVteps deviceVtep : sub.getDeviceVteps()) {
+ HwVtep hwVtep = ItmUtils.createHwVtepObject(deviceVtep.getTopologyId(), deviceVtep.getNodeId(),
+ deviceVtep.getIpAddress(), sub.getPrefix(), sub.getGatewayIp(), sub.getVlanId(),
+ tzone.getTunnelType(), tzone);
+ hwVteps.add(hwVtep);
+ }
+ }
+ }
+ }
+ LOG.debug("Update:Calling TunnelMonitorToggleWorker with tzone = {} and {}",tzone.getZoneName(),dataObjectModificationAfter.isEnabled());
+ ItmMonitorToggleWorker toggleWorker = new ItmMonitorToggleWorker(hwVteps, tzone.getZoneName(),
+ dataObjectModificationAfter.isEnabled(), broker, hwVtepsExist);
+ coordinator.enqueueJob(tzone.getZoneName(), toggleWorker);
+ }
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<TunnelMonitorEnabled> key, TunnelMonitorEnabled dataObjectModification) {
+ LOG.debug("add TunnelMonitorChangeListener called with {}",dataObjectModification.isEnabled());
+ List<HwVtep> hwVteps = new ArrayList<HwVtep>();
+ Boolean hwVtepsExist = false;
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ InstanceIdentifier<TransportZones> path = InstanceIdentifier.builder(TransportZones.class).build();
+ Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, broker);
+ if (tZonesOptional.isPresent()) {
+ TransportZones tZones = tZonesOptional.get();
+ for (TransportZone tzone : tZones.getTransportZone()) {
+ hwVtepsExist = false;
+ hwVteps = new ArrayList<HwVtep>();
+ if (tzone.getSubnets() != null && !tzone.getSubnets().isEmpty()) {
+ for (Subnets sub : tzone.getSubnets()) {
+ if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) {
+ hwVtepsExist = true;
+ for (DeviceVteps deviceVtep : sub.getDeviceVteps()) {
+ HwVtep hwVtep = ItmUtils.createHwVtepObject(deviceVtep.getTopologyId(), deviceVtep.getNodeId(),
+ deviceVtep.getIpAddress(), sub.getPrefix(), sub.getGatewayIp(), sub.getVlanId(),
+ tzone.getTunnelType(), tzone);
+ hwVteps.add(hwVtep);
+ }
+ }
+ }
+ }
+ LOG.debug("Add:Calling TunnelMonitorToggleWorker with tzone = {} and {}",tzone.getZoneName(),dataObjectModification.isEnabled());
+ ItmMonitorToggleWorker toggleWorker = new ItmMonitorToggleWorker(hwVteps, tzone.getZoneName(),
+ dataObjectModification.isEnabled(), broker, hwVtepsExist);
+ coordinator.enqueueJob(tzone.getZoneName(), toggleWorker);
+ }
+ }
+ }
+
+ @Override protected TunnelMonitorChangeListener getDataTreeChangeListener() {
+ return TunnelMonitorChangeListener.this;
+ }
+
+}
--- /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.itm.listeners;
+
+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.binding.api.WriteTransaction;
+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.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
+import org.opendaylight.vpnservice.itm.confighelpers.HwVtep;
+import org.opendaylight.vpnservice.itm.confighelpers.ItmMonitorIntervalWorker;
+import org.opendaylight.vpnservice.itm.confighelpers.ItmMonitorToggleWorker;
+import org.opendaylight.vpnservice.itm.confighelpers.ItmTepAddWorker;
+import org.opendaylight.vpnservice.itm.globals.ITMConstants;
+import org.opendaylight.vpnservice.itm.impl.ItmUtils;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+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.InterfaceBuilder;
+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.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.TunnelMonitorEnabled;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.TunnelMonitorInterval;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.ExternalTunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZone;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.DeviceVteps;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TunnelMonitorIntervalListener extends AsyncDataTreeChangeListenerBase<TunnelMonitorInterval, TunnelMonitorIntervalListener>
+ implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(TunnelMonitorIntervalListener.class);
+ private ListenerRegistration<DataChangeListener> monitorIntervalListenerRegistration;
+ private final DataBroker broker;
+
+ public TunnelMonitorIntervalListener(DataBroker db) {
+ super(TunnelMonitorInterval.class, TunnelMonitorIntervalListener.class);
+ broker = db;
+ }
+
+ @Override protected InstanceIdentifier<TunnelMonitorInterval> getWildCardPath() {
+ return InstanceIdentifier.create(TunnelMonitorInterval.class);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<TunnelMonitorInterval> key, TunnelMonitorInterval dataObjectModification) {
+ LOG.debug("remove TunnelMonitorIntervalListener called with {}",dataObjectModification.getInterval());
+ List<HwVtep> hwVteps = new ArrayList<HwVtep>();
+ Boolean hwVtepsExist = false;
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ InstanceIdentifier<TransportZones> path = InstanceIdentifier.builder(TransportZones.class).build();
+ Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, broker);
+ if (tZonesOptional.isPresent()) {
+ TransportZones tZones = tZonesOptional.get();
+ for (TransportZone tzone : tZones.getTransportZone()) {
+ /* hwVtepsExist = false;
+ hwVteps = new ArrayList<HwVtep>();
+ if (tzone.getSubnets() != null && !tzone.getSubnets().isEmpty()) {
+ for (Subnets sub : tzone.getSubnets()) {
+ if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) {
+ hwVtepsExist = true;
+ LOG.debug("Remove:Calling TunnelMonitorIntervalWorker with tzone = {} and hwtepExist",tzone.getZoneName());
+ for (DeviceVteps deviceVtep : sub.getDeviceVteps()) {
+ HwVtep hwVtep = ItmUtils.createHwVtepObject(deviceVtep.getTopologyId(), deviceVtep.getNodeId(),
+ deviceVtep.getIpAddress(), sub.getPrefix(), sub.getGatewayIp(), sub.getVlanId(),
+ tzone.getTunnelType(), tzone);
+ hwVteps.add(hwVtep);
+ }
+ }
+ }
+ }*/
+ //if you remove configuration, the last configured interval is only set i.e no change
+ LOG.debug("Remove:Calling TunnelMonitorIntervalWorker with tzone = {} and {}",tzone.getZoneName(),dataObjectModification.getInterval());
+ ItmMonitorIntervalWorker toggleWorker = new ItmMonitorIntervalWorker(hwVteps, tzone.getZoneName(),
+ dataObjectModification.getInterval(), broker, hwVtepsExist);
+ coordinator.enqueueJob(tzone.getZoneName(), toggleWorker);
+ }
+ }
+ }
+
+ @Override protected void update(InstanceIdentifier<TunnelMonitorInterval> key,
+ TunnelMonitorInterval dataObjectModificationBefore,
+ TunnelMonitorInterval dataObjectModificationAfter) {
+ LOG.debug("update TunnelMonitorIntervalListener called with {}",dataObjectModificationAfter.getInterval());
+ List<HwVtep> hwVteps = new ArrayList<HwVtep>();
+ Boolean hwVtepsExist = false;
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ InstanceIdentifier<TransportZones> path = InstanceIdentifier.builder(TransportZones.class).build();
+ Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, broker);
+ if (tZonesOptional.isPresent()) {
+ TransportZones tZones = tZonesOptional.get();
+ for (TransportZone tzone : tZones.getTransportZone()) {
+ /*hwVtepsExist = false;
+ hwVteps = new ArrayList<HwVtep>();
+ if (tzone.getSubnets() != null && !tzone.getSubnets().isEmpty()) {
+ for (Subnets sub : tzone.getSubnets()) {
+ if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) {
+ hwVtepsExist = true;//gets set to true only if this particular tzone has
+ LOG.debug("Update:Calling TunnelMonitorIntervalWorker with tzone = {} and hwtepExist",tzone.getZoneName());
+ for (DeviceVteps deviceVtep : sub.getDeviceVteps()) {
+ HwVtep hwVtep = ItmUtils.createHwVtepObject(deviceVtep.getTopologyId(), deviceVtep.getNodeId(),
+ deviceVtep.getIpAddress(), sub.getPrefix(), sub.getGatewayIp(), sub.getVlanId(),
+ tzone.getTunnelType(), tzone);
+ hwVteps.add(hwVtep);
+ }
+ }
+ }
+ }*/
+ LOG.debug("Update:Calling TunnelMonitorIntervalWorker with tzone = {} and {}",tzone.getZoneName(),dataObjectModificationAfter.getInterval());
+ ItmMonitorIntervalWorker intervalWorker = new ItmMonitorIntervalWorker(hwVteps, tzone.getZoneName(),
+ dataObjectModificationAfter.getInterval(), broker, hwVtepsExist);
+ coordinator.enqueueJob(tzone.getZoneName(), intervalWorker);
+ }
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<TunnelMonitorInterval> key, TunnelMonitorInterval dataObjectModification) {
+ LOG.debug("Add TunnelMonitorIntervalListener called with {}",dataObjectModification.getInterval());
+ List<HwVtep> hwVteps = new ArrayList<HwVtep>();
+ Boolean hwVtepsExist = false;
+ DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
+ InstanceIdentifier<TransportZones> path = InstanceIdentifier.builder(TransportZones.class).build();
+ Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, broker);
+ if (tZonesOptional.isPresent()) {
+ TransportZones tZones = tZonesOptional.get();
+ for (TransportZone tzone : tZones.getTransportZone()) {
+ /*hwVtepsExist = false;
+ hwVteps = new ArrayList<HwVtep>();
+ if (tzone.getSubnets() != null && !tzone.getSubnets().isEmpty()) {
+ for (Subnets sub : tzone.getSubnets()) {
+ if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) {
+ hwVtepsExist = true;
+ LOG.debug("Add:Calling TunnelMonitorIntervalWorker with tzone = {} and hwtepExist",tzone.getZoneName());
+ for (DeviceVteps deviceVtep : sub.getDeviceVteps()) {
+ HwVtep hwVtep = ItmUtils.createHwVtepObject(deviceVtep.getTopologyId(), deviceVtep.getNodeId(),
+ deviceVtep.getIpAddress(), sub.getPrefix(), sub.getGatewayIp(), sub.getVlanId(),
+ tzone.getTunnelType(), tzone);
+ hwVteps.add(hwVtep);
+ }
+ }
+ }
+ }*/
+ LOG.debug("Add:Calling TunnelMonitorIntervalWorker with tzone = {} and {}",tzone.getZoneName(),dataObjectModification.getInterval());
+ ItmMonitorIntervalWorker intervalWorker = new ItmMonitorIntervalWorker(hwVteps, tzone.getZoneName(),
+ dataObjectModification.getInterval(), broker, hwVtepsExist);
+ //conversion to milliseconds done while writing to i/f-mgr config DS
+ coordinator.enqueueJob(tzone.getZoneName(), intervalWorker);
+ }
+ }
+ }
+
+ @Override protected TunnelMonitorIntervalListener getDataTreeChangeListener() {
+ return TunnelMonitorIntervalListener.this;
+ }
+}
--- /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.itm.listeners;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.net.util.SubnetUtils;
+import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
+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.itm.cli.TepCommandHelper;
+import org.opendaylight.vpnservice.itm.globals.ITMConstants;
+import org.opendaylight.vpnservice.itm.impl.ItmUtils;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.VtepConfigSchemas;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.VtepConfigSchema;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.VtepConfigSchemaBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.ip.pools.VtepIpPool;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.ip.pools.VtepIpPoolBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.vtep.config.schema.DpnIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.config.rev151102.vtep.config.schemas.vtep.config.schema.DpnIdsKey;
+//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.rev151102.VtepConfigSchemas;
+//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.rev151102.vtep.config.schemas.VtepConfigSchema;
+//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.rev151102.vtep.config.schemas.VtepConfigSchemaBuilder;
+//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.rev151102.vtep.ip.pools.VtepIpPool;
+//import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.itm.config.rev151102.vtep.ip.pools.VtepIpPoolBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZone;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZoneKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.SubnetsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.Vteps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.VtepsKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+/**
+ * The listener class interested in processing data change on
+ * {@code VtepConfigSchema} objects.
+ *
+ * @see VtepConfigSchema
+ */
+public class VtepConfigSchemaListener extends AbstractDataChangeListener<VtepConfigSchema> implements AutoCloseable {
+
+ /** The Constant LOG. */
+ private static final Logger LOG = LoggerFactory.getLogger(VtepConfigSchemaListener.class);
+
+ /** The listener registration. */
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+
+ /** The data broker. */
+ private final DataBroker dataBroker;
+
+ /**
+ * Instantiates a new vtep config schema listener.
+ *
+ * @param db
+ * the db
+ */
+ public VtepConfigSchemaListener(final DataBroker db) {
+ super(VtepConfigSchema.class);
+ this.dataBroker = db;
+ registerListener(db);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.AutoCloseable#close()
+ */
+ @Override
+ public void close() throws Exception {
+ if (this.listenerRegistration != null) {
+ try {
+ this.listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ this.listenerRegistration = null;
+ }
+ LOG.info("VtepConfigSchemaListener Closed");
+ }
+
+ /**
+ * Register listener.
+ *
+ * @param db
+ * the db
+ */
+ private void registerListener(final DataBroker db) {
+ try {
+ this.listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ getWildCardPath(), VtepConfigSchemaListener.this, AsyncDataBroker.DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("VtepConfigSchemaListener DataChange listener registration fail!", e);
+ throw new IllegalStateException("VtepConfigSchemaListener registration Listener failed.", e);
+ }
+ }
+
+ /**
+ * Gets the wild card path.
+ *
+ * @return the wild card path
+ */
+ private InstanceIdentifier<VtepConfigSchema> getWildCardPath() {
+ return ItmUtils.getVtepConfigSchemaIdentifier();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener#remove(
+ * org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
+ * org.opendaylight.yangtools.yang.binding.DataObject)
+ */
+ @Override
+ protected void remove(InstanceIdentifier<VtepConfigSchema> identifier, VtepConfigSchema schema) {
+ LOG.trace("Received notification for VTEP config schema [{}] deleted.", schema.getSchemaName());
+ try {
+ List<BigInteger> lstDpnIds = ItmUtils.getDpnIdList(schema.getDpnIds());
+ if (lstDpnIds != null && !lstDpnIds.isEmpty()) {
+ deleteVteps(schema, lstDpnIds);
+ }
+
+ // Delete IP pool corresponding to schema
+ // TODO: Ensure no schema exists with same subnet before deleting
+ String subnetCidr = ItmUtils.getSubnetCidrAsString(schema.getSubnet());
+ deleteVtepIpPool(subnetCidr);
+ } catch (Exception e) {
+ String error = new StringBuilder("Failed to handle DCN for delete VtepConfigSchema: ").append(schema)
+ .toString();
+ LOG.error(error, e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener#update(
+ * org.opendaylight.yangtools.yang.binding.InstanceIdentifier,
+ * org.opendaylight.yangtools.yang.binding.DataObject,
+ * org.opendaylight.yangtools.yang.binding.DataObject)
+ */
+ @Override
+ protected void update(InstanceIdentifier<VtepConfigSchema> identifier, VtepConfigSchema original,
+ VtepConfigSchema updated) {
+ LOG.error("Receivedn DCN for updating VTEP Original schema: {}. Updated schema: {}",
+ original, updated);
+ //LOG.trace("Received notification for VTEP config schema [{}] updated.", original.getSchemaName());
+
+ try {
+ VtepConfigSchema orignalSchema = ItmUtils.validateVtepConfigSchema(original);
+ VtepConfigSchema updatedSchema = ItmUtils.validateVtepConfigSchema(updated);
+
+ if (doesDeleteAndAddSchemaRequired(original, updated)) {
+ LOG.error("Failed to handle DCN for updating VTEP schema {}. Original schema: {}. Updated schema: {}",
+ original, updated);
+ // TODO: handle updates
+ return;
+ }
+
+ handleUpdateOfDpnIds(orignalSchema, updatedSchema);
+
+ } catch (Exception e) {
+ String error = new StringBuilder("Failed to handle DCN for update VtepConfigSchema original:")
+ .append(original).append(", updated: ").append(updated).toString();
+ LOG.error(error, e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener#add(org.
+ * opendaylight.yangtools.yang.binding.InstanceIdentifier,
+ * org.opendaylight.yangtools.yang.binding.DataObject)
+ */
+ @Override
+ protected void add(InstanceIdentifier<VtepConfigSchema> identifier, VtepConfigSchema schema) {
+ // Construct the transport zones from the provided schemas and push it
+ // to config DS.
+ LOG.trace("Add VtepConfigSchema: key: {} , value: {}", identifier, schema);
+
+ try {
+ VtepConfigSchema validatedSchema = ItmUtils.validateForAddVtepConfigSchema(schema,
+ getAllVtepConfigSchemas());
+
+ VtepIpPool vtepIpPool = processAvailableIps(validatedSchema);
+ addVteps(validatedSchema, vtepIpPool);
+ } catch (Exception e) {
+ LOG.error("Failed to handle DCN for add VtepConfigSchema: {}", e);
+ }
+ }
+
+ /**
+ * Handle update of dpn ids.
+ *
+ * @param original
+ * the original
+ * @param updated
+ * the updated
+ */
+ private void handleUpdateOfDpnIds(VtepConfigSchema original, VtepConfigSchema updated) {
+ // Handling add/delete DPNs from schema
+ List<DpnIds> originalDpnIds = (original.getDpnIds() == null) ? new ArrayList<DpnIds>()
+ : original.getDpnIds();
+ List<DpnIds> updatedDpnIds = (updated.getDpnIds() == null) ? new ArrayList<DpnIds>()
+ : updated.getDpnIds();
+
+ handleDeletedDpnsFromSchema(original, originalDpnIds, updatedDpnIds);
+ handleNewlyAddedDpnsToSchema(original, originalDpnIds, updatedDpnIds);
+ }
+
+ /**
+ * Does delete and add schema required.
+ *
+ * @param original
+ * the original
+ * @param updated
+ * the updated
+ * @return true, if successful
+ */
+ private boolean doesDeleteAndAddSchemaRequired(VtepConfigSchema original, VtepConfigSchema updated) {
+ boolean delnAddRequired = false;
+ if (!StringUtils.equalsIgnoreCase(original.getPortName(), updated.getPortName())) {
+ delnAddRequired = true;
+ } else if (original.getVlanId() != updated.getVlanId()) {
+ delnAddRequired = true;
+ } else if (original.getSubnet() != null && !original.getSubnet().equals(updated.getSubnet())) {
+ delnAddRequired = true;
+ } else if (original.getGatewayIp() != null && !original.getGatewayIp().equals(updated.getGatewayIp())) {
+ delnAddRequired = true;
+ } else if (!StringUtils.equalsIgnoreCase(original.getTransportZoneName(), updated.getTransportZoneName())) {
+ delnAddRequired = true;
+ } else if (!(original.getTunnelType().equals(updated.getTunnelType()) )) {
+ delnAddRequired = true;
+ }
+ return delnAddRequired;
+ }
+
+ /**
+ * Handle newly added dpns to schema.
+ *
+ * @param original
+ * the original
+ * @param originalDpnIds
+ * the original dpn ids
+ * @param updatedDpnIds
+ * the updated dpn ids
+ */
+ private void handleNewlyAddedDpnsToSchema(VtepConfigSchema original, List<DpnIds> originalDpnIds,
+ List<DpnIds> updatedDpnIds) {
+ LOG.trace("Handle Addition of DPNs from VTEP Original Dpn: {}. Updated Dpn: {}", originalDpnIds, updatedDpnIds) ;
+ ArrayList<DpnIds> newlyAddedDpns = new ArrayList<>(updatedDpnIds);
+ newlyAddedDpns.removeAll(originalDpnIds);
+ LOG.debug("Newly added DPNs {} to VTEP config schema [{}].", newlyAddedDpns, original.getSchemaName());
+ if (!newlyAddedDpns.isEmpty()) {
+ VtepConfigSchema diffSchema = new VtepConfigSchemaBuilder(original).setDpnIds(newlyAddedDpns).build();
+ String subnetCidr = ItmUtils.getSubnetCidrAsString(original.getSubnet());
+ VtepIpPool vtepIpPool = getVtepIpPool(subnetCidr);
+ LOG.debug("Adding of DPNs in Diff Schema: {}", diffSchema) ;
+ addVteps(diffSchema, vtepIpPool);
+ }
+ }
+
+ /**
+ * Handle deleted dpns from schema.
+ *
+ * @param original
+ * the original
+ * @param originalDpnIds
+ * the original dpn ids
+ * @param updatedDpnIds
+ * the updated dpn ids
+ */
+ private void handleDeletedDpnsFromSchema(VtepConfigSchema original, List<DpnIds> originalDpnIds,
+ List<DpnIds> updatedDpnIds) {
+ ArrayList<DpnIds> deletedDpns = new ArrayList<>(originalDpnIds);
+ deletedDpns.removeAll(updatedDpnIds);
+ LOG.debug("DPNs to be removed DPNs {} from VTEP config schema [{}].", deletedDpns, original.getSchemaName());
+ if (!deletedDpns.isEmpty()) {
+ LOG.debug("Deleting of DPNs from VTEP Schema: {}. To be deleted Dpns: {}", original, deletedDpns) ;
+ deleteVteps(original, ItmUtils.getDpnIdList(deletedDpns));
+ }
+ }
+
+ /**
+ * Gets all vtep config schemas.
+ *
+ * @return the all vtep config schemas
+ */
+ private List<VtepConfigSchema> getAllVtepConfigSchemas() {
+ Optional<VtepConfigSchemas> schemas = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
+ ItmUtils.getVtepConfigSchemasIdentifier(), this.dataBroker);
+ if (schemas.isPresent()) {
+ return schemas.get().getVtepConfigSchema();
+ }
+ return null;
+ }
+
+ /**
+ * Adds the vteps.
+ *
+ * @param schema
+ * the schema
+ * @param vtepIpPool
+ * the vtep ip pool
+ */
+ private void addVteps(VtepConfigSchema schema, VtepIpPool vtepIpPool) {
+ if (schema.getDpnIds() == null || schema.getDpnIds().isEmpty()) {
+ LOG.debug("DPN list is empty, skipping addVteps for schema: {}", schema);
+ return;
+ }
+
+ String subnetCidr = ItmUtils.getSubnetCidrAsString(schema.getSubnet());
+ if (vtepIpPool == null) {
+ LOG.error("VTEP config pool not found for subnetCidr {}. Failed to add VTEPs for schema {}", subnetCidr,
+ schema);
+ return;
+ }
+ TepCommandHelper tepCommandHelper = new TepCommandHelper(this.dataBroker);
+ // Check this later
+ String tunType ;
+ Class<? extends TunnelTypeBase> tunnelType = schema.getTunnelType() ;
+ if( tunnelType.equals(TunnelTypeVxlan.class))
+ tunType = ITMConstants.TUNNEL_TYPE_VXLAN ;
+ else
+ tunType = ITMConstants.TUNNEL_TYPE_GRE;
+ tepCommandHelper.configureTunnelType(schema.getTransportZoneName(),
+ StringUtils.upperCase(tunType));
+
+ List<IpAddress> availableIps = vtepIpPool.getAvailableIpaddress();
+ List<IpAddress> newlyAllocatedIps = new ArrayList<>();
+ List<BigInteger> skippedDpnIds = new ArrayList<>();
+
+ String gatewayIp = handleGatewayIp(schema.getGatewayIp());
+ for (BigInteger dpnId : ItmUtils.getDpnIdList(schema.getDpnIds())) {
+ IpAddress ipAddress = getAnAvailableIP(availableIps);
+ if (ipAddress == null) {
+ skippedDpnIds.add(dpnId);
+ continue;
+ }
+ tepCommandHelper.createLocalCache(dpnId, schema.getPortName(), schema.getVlanId(),
+ String.valueOf(ipAddress.getValue()), subnetCidr, gatewayIp, schema.getTransportZoneName());
+ newlyAllocatedIps.add(ipAddress);
+ }
+ if (!skippedDpnIds.isEmpty()) {
+ LOG.error("No available IP addresses in the VTEP config pool {}, skipping VTEP configurations for DPN's {}",
+ subnetCidr, skippedDpnIds);
+ }
+
+ if (!newlyAllocatedIps.isEmpty()) {
+ LOG.debug( "Delete OnCommit and buildTeps in NewlyAddedDpns");
+ tepCommandHelper.deleteOnCommit();
+ tepCommandHelper.buildTeps();
+ allocateIpAddresses(newlyAllocatedIps, vtepIpPool, subnetCidr);
+ }
+ }
+
+ /**
+ * Handle gateway ip.
+ *
+ * @param gatewayIp
+ * the gateway ip
+ * @return the string
+ */
+ private String handleGatewayIp(IpAddress gatewayIp) {
+ String strGatewayIp = (gatewayIp == null) ? null : String.valueOf(gatewayIp.getValue());
+ if (StringUtils.isBlank(strGatewayIp) || StringUtils.equals(ITMConstants.DUMMY_IP_ADDRESS, strGatewayIp)) {
+ // To avoid a validation exception in TepCommandHelper
+ strGatewayIp = null;
+ }
+ return strGatewayIp;
+ }
+
+ /**
+ * Delete vteps.
+ *
+ * @param schema
+ * the schema
+ * @param lstDpnIdsToBeDeleted
+ * the dpn ids list to be deleted
+ */
+ private void deleteVteps(VtepConfigSchema schema, List<BigInteger> lstDpnIdsToBeDeleted) {
+ TepCommandHelper tepCommandHelper = new TepCommandHelper(this.dataBroker);
+ List<IpAddress> freeIps = new ArrayList<>();
+
+ String subnetCidr = ItmUtils.getSubnetCidrAsString(schema.getSubnet());
+ String gatewayIp = handleGatewayIp(schema.getGatewayIp());
+
+ for (BigInteger dpnId : lstDpnIdsToBeDeleted) {
+ VtepsKey vtepkey = new VtepsKey(dpnId, schema.getPortName());
+
+ InstanceIdentifier<Vteps> vpath = InstanceIdentifier.builder(TransportZones.class)
+ .child(TransportZone.class, new TransportZoneKey(schema.getTransportZoneName()))
+ .child(Subnets.class, new SubnetsKey(schema.getSubnet())).child(Vteps.class, vtepkey).build();
+
+ Vteps vtep = null;
+ Optional<Vteps> vtepOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, vpath, dataBroker);
+ if (vtepOptional.isPresent()) {
+ vtep = vtepOptional.get();
+ } else {
+ LOG.warn("VTEP doesn't exist for DPN [{}] and port [{}].", dpnId, schema.getPortName());
+ continue;
+ }
+
+ IpAddress ipAddress = vtep.getIpAddress();
+ tepCommandHelper.deleteVtep(dpnId, vtep.getPortname(), schema.getVlanId(),
+ String.valueOf(ipAddress.getValue()), subnetCidr, gatewayIp, schema.getTransportZoneName());
+
+ freeIps.add(ipAddress);
+ }
+ LOG.debug( "Delete OnCommit in NewlyAddedDpns");
+ tepCommandHelper.deleteOnCommit();
+ deAllocateIpAddresses(freeIps, subnetCidr);
+ }
+
+ /**
+ * Calculate available IPs from the subnet mask specified in the schema.
+ * Pushes the available and allocated IP address to config DS.
+ *
+ * @param schema
+ * the schema
+ */
+ private VtepIpPool processAvailableIps(final VtepConfigSchema schema) {
+ String subnetCidr = ItmUtils.getSubnetCidrAsString(schema.getSubnet());
+ SubnetUtils subnetUtils = new SubnetUtils(subnetCidr);
+
+ List<IpAddress> availableIps = calculateAvailableIps(subnetUtils, schema.getExcludeIpFilter(),
+ schema.getGatewayIp());
+ VtepIpPool vtepIpPool = new VtepIpPoolBuilder().setSubnetCidr(subnetCidr).setAvailableIpaddress(availableIps)
+ .setAllocatedIpaddress(new ArrayList<IpAddress>()).build();
+
+ MDSALUtil.syncWrite(this.dataBroker, LogicalDatastoreType.CONFIGURATION,
+ ItmUtils.getVtepIpPoolIdentifier(subnetCidr), vtepIpPool);
+ LOG.info("Vtep IP Pool with key:{} added to config DS", subnetCidr);
+ return vtepIpPool;
+ }
+
+ /**
+ * Gets the vtep ip pool.
+ *
+ * @param subnetCidr
+ * the subnet cidr
+ * @return the vtep ip pool
+ */
+ private VtepIpPool getVtepIpPool(final String subnetCidr) {
+ Optional<VtepIpPool> vtepIpPool = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
+ ItmUtils.getVtepIpPoolIdentifier(subnetCidr), this.dataBroker);
+ if (vtepIpPool.isPresent()) {
+ return vtepIpPool.get();
+ }
+ return null;
+ }
+
+ /**
+ * Delete vtep ip pool.
+ *
+ * @param subnetCidr
+ * the subnet cidr
+ */
+ private void deleteVtepIpPool(final String subnetCidr) {
+ if (StringUtils.isNotBlank(subnetCidr)) {
+ MDSALUtil.syncDelete(this.dataBroker, LogicalDatastoreType.CONFIGURATION,
+ ItmUtils.getVtepIpPoolIdentifier(subnetCidr));
+ LOG.debug("Deleted Vtep IP Pool with key:{}", subnetCidr);
+ }
+ }
+
+ /**
+ * Gets the an available ip.
+ *
+ * @param availableIps
+ *
+ * @return the an available ip
+ */
+ private IpAddress getAnAvailableIP(List<IpAddress> availableIps) {
+ // TODO: Sort IP Addresses, get the least value
+ IpAddress ipAddress = null;
+ if (availableIps != null && !availableIps.isEmpty()) {
+ ipAddress = availableIps.remove(0);
+ }
+ return ipAddress;
+ }
+
+ /**
+ * Allocate ip addresses.
+ *
+ * @param allocatedIps
+ * the allocated ips
+ * @param vtepIpPool
+ * the vtep ip pool
+ * @param subnetCidr
+ * the subnet cidr
+ */
+ private void allocateIpAddresses(List<IpAddress> allocatedIps, VtepIpPool vtepIpPool, String subnetCidr) {
+ if (allocatedIps != null && !allocatedIps.isEmpty() && vtepIpPool != null) {
+ // Remove from the available IP address list and add to allocated IP
+ // address list.
+ VtepIpPoolBuilder builder = new VtepIpPoolBuilder(vtepIpPool);
+ if (builder.getAvailableIpaddress() != null) {
+ builder.getAvailableIpaddress().removeAll(allocatedIps);
+ }
+ if (builder.getAllocatedIpaddress() == null) {
+ builder.setAllocatedIpaddress(allocatedIps);
+ } else {
+ builder.getAllocatedIpaddress().addAll(allocatedIps);
+ }
+
+ MDSALUtil.syncWrite(this.dataBroker, LogicalDatastoreType.CONFIGURATION,
+ ItmUtils.getVtepIpPoolIdentifier(subnetCidr), builder.build());
+ }
+ }
+
+ /**
+ * De-allocate ip addresses.
+ *
+ * @param freeIps
+ * the free ips
+ * @param subnetCidr
+ * the subnet cidr
+ */
+ private void deAllocateIpAddresses(List<IpAddress> freeIps, String subnetCidr) {
+ VtepIpPool vtepIpPool = getVtepIpPool(subnetCidr);
+ if (freeIps != null && !freeIps.isEmpty() && vtepIpPool != null) {
+ // Remove from the allocated IP address list and add to available IP
+ // address list.
+ VtepIpPoolBuilder builder = new VtepIpPoolBuilder(vtepIpPool);
+ if (builder.getAllocatedIpaddress() != null) {
+ builder.getAllocatedIpaddress().removeAll(freeIps);
+ }
+ if (builder.getAvailableIpaddress() == null) {
+ builder.setAvailableIpaddress(freeIps);
+ } else {
+ builder.getAvailableIpaddress().addAll(freeIps);
+ }
+
+ MDSALUtil.syncWrite(this.dataBroker, LogicalDatastoreType.CONFIGURATION,
+ ItmUtils.getVtepIpPoolIdentifier(subnetCidr), builder.build());
+ LOG.debug("Vtep IP Pool with key:{} updated to config DS", subnetCidr);
+ }
+ }
+
+ /**
+ * Calculate available ips.
+ *
+ * @param subnetCidr
+ * the subnet cidr
+ * @param excludeIpFilter
+ * the exclude ip filter
+ * @param gatewayIp
+ * the gateway IP
+ * @return the list
+ */
+ private List<IpAddress> calculateAvailableIps(SubnetUtils subnetUtils, String excludeIpFilter,
+ IpAddress gatewayIp) {
+ List<IpAddress> lstAvailableIps = new ArrayList<>();
+ SubnetInfo subnetInfo = subnetUtils.getInfo();
+ String[] arrIpAddresses = subnetInfo.getAllAddresses();
+
+ for (String ipAddress : arrIpAddresses) {
+ lstAvailableIps.add(new IpAddress(ipAddress.toCharArray()));
+ }
+ lstAvailableIps.remove(gatewayIp);
+ lstAvailableIps.removeAll(ItmUtils.getExcludeIpAddresses(excludeIpFilter, subnetInfo));
+
+ return lstAvailableIps;
+ }
+}
--- /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.itm.monitoring;
+
+import javax.management.AttributeChangeNotification;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import java.util.ArrayList;
+
+/**
+ * Created by emnqrrw on 10/27/2015.
+ */
+public class DataPathAlarm extends NotificationBroadcasterSupport implements DataPathAlarmMBean {
+
+ ArrayList<String> raiseAlarmObject = new ArrayList<String>();
+ ArrayList<String> clearAlarmObject = new ArrayList<String>();
+ private long sequenceNumber = 1;
+
+ public void setRaiseAlarmObject(ArrayList<String> raiseAlarmObject) {
+ this.raiseAlarmObject = raiseAlarmObject;
+
+ Notification n = new AttributeChangeNotification(this,
+ sequenceNumber++, System.currentTimeMillis(),
+ "raise alarm object notified ", "raiseAlarmObject", "ArrayList",
+ "", this.raiseAlarmObject);
+ sendNotification(n);
+ }
+
+ public ArrayList<String> getRaiseAlarmObject() {
+ return raiseAlarmObject;
+ }
+
+ public void setClearAlarmObject(ArrayList<String> clearAlarmObject) {
+ this.clearAlarmObject = clearAlarmObject;
+
+ Notification n = new AttributeChangeNotification(this,
+ sequenceNumber++, System.currentTimeMillis(),
+ "clear alarm object notified ", "clearAlarmObject", "ArrayList",
+ "", this.clearAlarmObject);
+ sendNotification(n);
+ }
+
+ public ArrayList<String> getClearAlarmObject() {
+ return clearAlarmObject;
+ }
+
+ public synchronized void raiseAlarm(String alarmName, String additionalText, String source){
+ raiseAlarmObject.add(alarmName);
+ raiseAlarmObject.add(additionalText);
+ raiseAlarmObject.add(source);
+ setRaiseAlarmObject(raiseAlarmObject);
+ raiseAlarmObject.clear();
+ }
+ public synchronized void clearAlarm(String alarmName, String additionalText, String source){
+ clearAlarmObject.add(alarmName);
+ clearAlarmObject.add(additionalText);
+ clearAlarmObject.add(source);
+ setClearAlarmObject(clearAlarmObject);
+ clearAlarmObject.clear();
+ }
+}
--- /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.itm.monitoring;
+
+import java.util.ArrayList;
+
+/**
+ * Created by emnqrrw on 10/27/2015.
+ */
+public interface DataPathAlarmMBean {
+ public void setRaiseAlarmObject(ArrayList<String> raiseAlarmObject);
+ public ArrayList<String> getRaiseAlarmObject();
+ public void setClearAlarmObject(ArrayList<String> clearAlarmObject);
+ public ArrayList<String> getClearAlarmObject();
+ public void raiseAlarm(String alarmName, String additionalText, String source);
+ public void clearAlarm(String alarmName, String additionalText, String source);
+}
--- /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.itm.monitoring;
+
+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.itm.impl.ItmUtils;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+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.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel;
+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;
+
+/**
+ * Created by emnqrrw on 11/2/2015.
+ */
+public class ItmTunnelEventListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
+
+ private static final Logger logger = LoggerFactory.getLogger(ItmTunnelEventListener.class);
+ private final DataBroker broker;
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ public static final JMXAlarmAgent alarmAgent = new JMXAlarmAgent();
+
+ public ItmTunnelEventListener(final DataBroker db){
+ super(Interface.class);
+ broker = db;
+ registerListener(db);
+ alarmAgent.registerMbean();
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = broker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), ItmTunnelEventListener.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<Interface> getWildCardPath() {
+ return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Interface> identifier, Interface del) {
+ String ifName = del.getName() ;
+ if( del.getType() != null && del.getType().equals(Tunnel.class)) {
+ InternalTunnel internalTunnel = ItmUtils.getInternalTunnel(ifName,broker);
+ if( internalTunnel != null) {
+ BigInteger srcDpId = internalTunnel.getSourceDPN();
+ BigInteger dstDpId = internalTunnel.getDestinationDPN();
+ String tunnelType = ItmUtils.convertTunnelTypetoString(internalTunnel.getTransportType());
+ logger.trace("ITM Tunnel removed b/w srcDpn: {} and dstDpn: {} for tunnelType: {}", srcDpId, dstDpId, tunnelType);
+ clearInternalDataPathAlarm(srcDpId.toString(),dstDpId.toString(),tunnelType);
+ }else {
+ ExternalTunnel externalTunnel = ItmUtils.getExternalTunnel(ifName,broker);
+ if( externalTunnel != null) {
+ String srcNode = externalTunnel.getSourceDevice();
+ String dstNode = externalTunnel.getDestinationDevice();
+ String tunnelType = ItmUtils.convertTunnelTypetoString(externalTunnel.getTransportType());
+ logger.trace("ITM Tunnel removed b/w srcNode: {} and dstNode: {} for tunnelType: {}", srcNode, dstNode, tunnelType);
+ clearExternalDataPathAlarm(srcNode,dstNode,tunnelType);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Interface> identifier, Interface original, Interface update) {
+ String ifName = update.getName() ;
+ if( update.getType() != null && update.getType().equals(Tunnel.class)) {
+ InternalTunnel internalTunnel = ItmUtils.getInternalTunnel(ifName,broker);
+ if( internalTunnel != null) {
+ BigInteger srcDpId = internalTunnel.getSourceDPN();
+ BigInteger dstDpId = internalTunnel.getDestinationDPN();
+ String tunnelType = ItmUtils.convertTunnelTypetoString(internalTunnel.getTransportType());
+ logger.trace("ITM Tunnel state event changed from :{} to :{} for Tunnel Interface - {}", isTunnelInterfaceUp(original), isTunnelInterfaceUp(update), ifName);
+ if(isTunnelInterfaceUp(update)) {
+ logger.trace("ITM Tunnel State is UP b/w srcDpn: {} and dstDpn: {} for tunnelType {} ", srcDpId, dstDpId, tunnelType);
+ clearInternalDataPathAlarm(srcDpId.toString(),dstDpId.toString(),tunnelType);
+ }else {
+ logger.trace("ITM Tunnel State is DOWN b/w srcDpn: {} and dstDpn: {}", srcDpId, dstDpId);
+ StringBuilder alarmText = new StringBuilder();
+ alarmText.append("Data Path Connectivity is lost between ").append("openflow:").append(srcDpId).append(" and openflow:")
+ .append(dstDpId).append(" for tunnelType:").append(tunnelType);
+ raiseInternalDataPathAlarm(srcDpId.toString(), dstDpId.toString(), tunnelType,alarmText.toString());
+ }
+ }else{
+ ExternalTunnel externalTunnel = ItmUtils.getExternalTunnel(ifName,broker);
+ if( externalTunnel != null) {
+ String srcNode = externalTunnel.getSourceDevice();
+ String dstNode = externalTunnel.getDestinationDevice();
+ String tunnelType = ItmUtils.convertTunnelTypetoString(externalTunnel.getTransportType());
+ logger.trace("ITM Tunnel state event changed from :{} to :{} for Tunnel Interface - {}", isTunnelInterfaceUp(original), isTunnelInterfaceUp(update), ifName);
+ if(isTunnelInterfaceUp(update)) {
+ logger.trace("ITM Tunnel State is UP b/w srcNode: {} and dstNode: {} for tunnelType: {}", srcNode, dstNode, tunnelType);
+ clearExternalDataPathAlarm(srcNode.toString(),dstNode.toString(),tunnelType);
+ }else {
+ logger.trace("ITM Tunnel State is DOWN b/w srcNode: {} and dstNode: {}", srcNode, dstNode);
+ StringBuilder alarmText = new StringBuilder();
+ alarmText.append("Data Path Connectivity is lost between ").append(srcNode).append(dstNode).append(" for tunnelType:").append(tunnelType);
+ raiseExternalDataPathAlarm(srcNode, dstNode, tunnelType,alarmText.toString());
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Interface> identifier, Interface add) {
+ String ifName = add.getName() ;
+ if( add.getType() != null && add.getType().equals(Tunnel.class)) {
+ InternalTunnel internalTunnel = ItmUtils.getInternalTunnel(ifName,broker);
+ if( internalTunnel != null) {
+ BigInteger srcDpId = internalTunnel.getSourceDPN();
+ BigInteger dstDpId = internalTunnel.getDestinationDPN();
+ String tunnelType = ItmUtils.convertTunnelTypetoString(internalTunnel.getTransportType());
+ if(!isTunnelInterfaceUp(add)) {
+ logger.trace("ITM Tunnel State during tep add is DOWN b/w srcDpn: {} and dstDpn: {} for tunnelType: {}", srcDpId, dstDpId, tunnelType);
+ StringBuilder alarmText = new StringBuilder();
+ alarmText.append("Data Path Connection is down between ").append("openflow:").append(srcDpId).append(" and openflow:")
+ .append(dstDpId).append(" for tunnelType:").append(tunnelType).append(" during initial state");
+ raiseInternalDataPathAlarm(srcDpId.toString(), dstDpId.toString(), tunnelType, alarmText.toString());
+ }
+ }else {
+ ExternalTunnel externalTunnel = ItmUtils.getExternalTunnel(ifName,broker);
+ if( externalTunnel != null) {
+ String srcNode = externalTunnel.getSourceDevice();
+ String dstNode = externalTunnel.getDestinationDevice();
+ String tunnelType = ItmUtils.convertTunnelTypetoString(externalTunnel.getTransportType());
+ if(!isTunnelInterfaceUp(add)) {
+ logger.trace("ITM Tunnel State during tep add is DOWN b/w srcNode: {} and dstNode: {} for tunnelType: {}", srcNode, dstNode, tunnelType);
+ StringBuilder alarmText = new StringBuilder();
+ alarmText.append("Data Path Connection is down between ").append(srcNode).append(dstNode).append(" for tunnelType:").append(tunnelType).append(" during initial state");
+ raiseExternalDataPathAlarm(srcNode, dstNode, tunnelType,alarmText.toString());
+ }
+ }
+ }
+ }
+ }
+
+ @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;
+ }
+ }
+
+ public void raiseInternalDataPathAlarm(String srcDpnId,String dstDpnId,String tunnelType,String alarmText) {
+
+ StringBuilder source = new StringBuilder();
+ source.append("srcDpn=openflow:").append(srcDpnId).append("-dstDpn=openflow:").append(dstDpnId).append("-tunnelType").append(tunnelType);
+
+ logger.trace("Raising DataPathConnectionFailure alarm... alarmText {} source {} ", alarmText, source);
+ //Invokes JMX raiseAlarm method
+ alarmAgent.invokeFMraisemethod("DataPathConnectionFailure", alarmText, source.toString());
+ }
+
+ public void clearInternalDataPathAlarm(String srcDpnId,String dstDpnId,String tunnelType) {
+ StringBuilder source = new StringBuilder();
+
+ source.append("srcDpn=openflow:").append(srcDpnId).append("-dstDpn=openflow:").append(dstDpnId).append("-tunnelType").append(tunnelType);
+ logger.trace("Clearing DataPathConnectionFailure alarm of source {} ", source);
+ //Invokes JMX clearAlarm method
+ alarmAgent.invokeFMclearmethod("DataPathConnectionFailure", "Clearing ITM Tunnel down alarm", source.toString());
+ }
+
+ public void raiseExternalDataPathAlarm(String srcDevice,String dstDevice,String tunnelType, String alarmText) {
+
+ StringBuilder source = new StringBuilder();
+ source.append("srcDevice=").append(srcDevice).append("-dstDevice=").append(dstDevice).append("-tunnelType").append(tunnelType);
+
+ logger.trace("Raising DataPathConnectionFailure alarm... alarmText {} source {} ", alarmText, source);
+ //Invokes JMX raiseAlarm method
+ alarmAgent.invokeFMraisemethod("DataPathConnectionFailure", alarmText, source.toString());
+ }
+
+
+ public void clearExternalDataPathAlarm(String srcDevice,String dstDevice,String tunnelType) {
+
+ StringBuilder source = new StringBuilder();
+
+ source.append("srcDevice=").append(srcDevice).append("-dstDevice=").append(dstDevice).append("-tunnelType").append(tunnelType);
+
+ //logger.trace("Clearing DataPathConnectionFailure alarm of source {} ", source);
+ //Invokes JMX clearAlarm method
+ alarmAgent.invokeFMclearmethod("DataPathConnectionFailure", "Clearing ITM Tunnel down alarm", source.toString());
+
+ }
+
+ private boolean isTunnelInterfaceUp( Interface intf) {
+ boolean interfaceUp = (intf.getOperStatus().equals(Interface.OperStatus.Up)) ? true :false ;
+ return interfaceUp ;
+ }
+
+}
--- /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.itm.monitoring;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.management.*;
+import java.lang.management.ManagementFactory;
+/**
+ * Created by emnqrrw on 11/2/2015.
+ */
+public class JMXAlarmAgent {
+ static Logger s_logger = LoggerFactory.getLogger(JMXAlarmAgent.class);
+ private MBeanServer mbs = null;
+ private ObjectName alarmName = null;
+ private static final String BEANNAME = "SDNC.FM:name=DataPathAlarmBean";
+ private static DataPathAlarm alarmBean= new DataPathAlarm();
+
+ public JMXAlarmAgent() {
+ // Get the platform MBeanServer
+ mbs = ManagementFactory.getPlatformMBeanServer();
+ try {
+ alarmName = new ObjectName(BEANNAME);
+ } catch (MalformedObjectNameException e) {
+ s_logger.error("ObjectName instance creation failed for BEANAME {} : {}",BEANNAME, e);
+ }
+ }
+
+ public void registerMbean() {
+ // Unique identification of MBeans
+ try {
+ // Uniquely identify the MBeans and register them with the platform MBeanServer
+ if(!mbs.isRegistered(alarmName)) {
+ mbs.registerMBean(alarmBean, alarmName);
+ s_logger.debug("Registered Mbean {} successfully", alarmName);
+ }
+ } catch(Exception e) {
+ s_logger.error("Registeration failed for Mbean {} :{}", alarmName,e);
+ }
+ }
+
+ public void unregisterMbean() {
+ try {
+ if(mbs.isRegistered(alarmName)) {
+ mbs.unregisterMBean(alarmName);
+ s_logger.debug("Unregistered Mbean {} successfully", alarmName);
+ }
+ } catch (Exception e) {
+ s_logger.error("UnRegisteration failed for Mbean {} :{}", alarmName,e);
+ }
+ }
+
+ public void invokeFMraisemethod(String alarmId,String text,String src) {
+ try {
+ mbs.invoke(alarmName, "raiseAlarm", new Object[]{alarmId, text, src}, new String[]{String.class.getName(), String.class.getName(), String.class.getName()});
+ s_logger.trace("Invoked raiseAlarm function for Mbean {} with source {}", BEANNAME, src);
+ } catch (Exception e) {
+ s_logger.error("Invoking raiseAlarm method failed for Mbean {} :{}", alarmName,e);
+ }
+ }
+
+ public void invokeFMclearmethod(String alarmId,String text,String src) {
+ try {
+ mbs.invoke(alarmName, "clearAlarm", new Object[]{alarmId, text, src}, new String[]{String.class.getName(), String.class.getName(), String.class.getName()});
+ s_logger.trace("Invoked clearAlarm function for Mbean {} with source {}",BEANNAME,src);
+ } catch (Exception e) {
+ s_logger.error("Invoking clearAlarm method failed for Mbean {} :{}", alarmName,e);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.itm.rpc;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.vpnservice.mdsalutil.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeMplsOverGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.TransportZones;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZone;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.TransportZoneKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.SubnetsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.DeviceVteps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.DeviceVtepsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rev150701.transport.zones.transport.zone.subnets.DeviceVtepsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.vpnservice.itm.confighelpers.ItmExternalTunnelAddWorker;
+import org.opendaylight.vpnservice.itm.confighelpers.ItmExternalTunnelDeleteWorker;
+import org.opendaylight.vpnservice.itm.globals.ITMConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.vpnservice.itm.impl.ItmUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.ExternalTunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.TunnelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.external.tunnel.list.ExternalTunnelKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.tunnel.list.InternalTunnelKey;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+
+public class ItmManagerRpcService implements ItmRpcService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ItmManagerRpcService.class);
+ DataBroker dataBroker;
+ private IMdsalApiManager mdsalManager;
+
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ IdManagerService idManagerService;
+
+ public ItmManagerRpcService(DataBroker dataBroker, IdManagerService idManagerService) {
+ this.dataBroker = dataBroker;
+ this.idManagerService = idManagerService;
+ }
+
+ @Override
+ public Future<RpcResult<GetTunnelInterfaceNameOutput>> getTunnelInterfaceName(GetTunnelInterfaceNameInput input) {
+ RpcResultBuilder<GetTunnelInterfaceNameOutput> resultBld = null;
+ BigInteger sourceDpn = input.getSourceDpid() ;
+ BigInteger destinationDpn = input.getDestinationDpid() ;
+ InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(
+ TunnelList.class)
+ .child(InternalTunnel.class, new InternalTunnelKey(destinationDpn, sourceDpn, input.getTunnelType()));
+
+ Optional<InternalTunnel> tnl = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
+
+ if( tnl != null && tnl.isPresent())
+ {
+ InternalTunnel tunnel = tnl.get();
+ GetTunnelInterfaceNameOutputBuilder output = new GetTunnelInterfaceNameOutputBuilder() ;
+ output.setInterfaceName(tunnel.getTunnelInterfaceName()) ;
+ resultBld = RpcResultBuilder.success();
+ resultBld.withResult(output.build()) ;
+ }else {
+ resultBld = RpcResultBuilder.failed();
+ }
+
+ return Futures.immediateFuture(resultBld.build());
+ }
+
+
+ @Override
+ public Future<RpcResult<Void>> removeExternalTunnelEndpoint(
+ RemoveExternalTunnelEndpointInput input) {
+ //Ignore the Futures for now
+ final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+ List<DPNTEPsInfo> meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker) ;
+ ItmExternalTunnelDeleteWorker.deleteTunnels(dataBroker, idManagerService,meshedDpnList , input.getDestinationIp(), input.getTunnelType());
+ result.set(RpcResultBuilder.<Void>success().build());
+ return result;
+ }
+
+ @Override
+ public Future<RpcResult<Void>> removeExternalTunnelFromDpns(
+ RemoveExternalTunnelFromDpnsInput input) {
+ //Ignore the Futures for now
+ final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+ List<DPNTEPsInfo> cfgDpnList = ItmUtils.getDPNTEPListFromDPNId(dataBroker, input.getDpnId()) ;
+ ItmExternalTunnelDeleteWorker.deleteTunnels(dataBroker, idManagerService, cfgDpnList, input.getDestinationIp(), input.getTunnelType());
+ result.set(RpcResultBuilder.<Void>success().build());
+ return result;
+ }
+
+ @Override
+ public Future<RpcResult<Void>> buildExternalTunnelFromDpns(
+ BuildExternalTunnelFromDpnsInput input) {
+ //Ignore the Futures for now
+ final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+ List<ListenableFuture<Void>> extTunnelResultList = ItmExternalTunnelAddWorker.buildTunnelsFromDpnToExternalEndPoint(dataBroker, idManagerService,input.getDpnId(), input.getDestinationIp(), input.getTunnelType());
+ for (ListenableFuture<Void> extTunnelResult : extTunnelResultList) {
+ Futures.addCallback(extTunnelResult, new FutureCallback<Void>(){
+
+ @Override
+ public void onSuccess(Void aVoid) {
+ result.set(RpcResultBuilder.<Void>success().build());
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ String msg = String.format("Unable to create ext tunnel");
+ LOG.error("create ext tunnel failed. {}. {}", msg, error);
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
+ }
+ });
+ }
+ result.set(RpcResultBuilder.<Void>success().build());
+ return result;
+ }
+
+ @Override
+ public Future<RpcResult<Void>> addExternalTunnelEndpoint(
+ AddExternalTunnelEndpointInput input) {
+ // TODO Auto-generated method stub
+
+ //Ignore the Futures for now
+ final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+ List<DPNTEPsInfo> meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker) ;
+ ItmExternalTunnelAddWorker.buildTunnelsToExternalEndPoint(dataBroker, idManagerService,meshedDpnList, input.getDestinationIp(), input.getTunnelType()) ;
+ result.set(RpcResultBuilder.<Void>success().build());
+ return result;
+ }
+
+ @Override
+ public Future<RpcResult<GetExternalTunnelInterfaceNameOutput>> getExternalTunnelInterfaceName(
+ GetExternalTunnelInterfaceNameInput input) {
+ final SettableFuture<RpcResult<GetExternalTunnelInterfaceNameOutput>> result = SettableFuture.create() ;
+ RpcResultBuilder<GetExternalTunnelInterfaceNameOutput> resultBld;
+ String sourceNode = input.getSourceNode();
+ String dstNode = input.getDestinationNode();
+ InstanceIdentifier<ExternalTunnel> path = InstanceIdentifier.create(
+ ExternalTunnelList.class)
+ .child(ExternalTunnel.class, new ExternalTunnelKey(dstNode, sourceNode, input.getTunnelType()));
+
+ Optional<ExternalTunnel> ext = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
+
+ if( ext != null && ext.isPresent())
+ {
+ ExternalTunnel exTunnel = ext.get();
+ GetExternalTunnelInterfaceNameOutputBuilder output = new GetExternalTunnelInterfaceNameOutputBuilder() ;
+ output.setInterfaceName(exTunnel.getTunnelInterfaceName()) ;
+ resultBld = RpcResultBuilder.success();
+ resultBld.withResult(output.build()) ;
+ }else {
+ resultBld = RpcResultBuilder.failed();
+ }
+
+ return Futures.immediateFuture(resultBld.build());
+ }
+
+ @Override
+ public Future<RpcResult<java.lang.Void>> createTerminatingServiceActions(final CreateTerminatingServiceActionsInput input) {
+ LOG.info("create terminatingServiceAction on DpnId = {} for service id {} and instructions {}", input.getDpnId() , input.getServiceId(), input.getInstruction());
+ final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+ int serviceId = input.getServiceId() ;
+ List<MatchInfo> mkMatches = getTunnelMatchesForServiceId(serviceId);
+ byte[] vxLANHeader = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ // Flags Byte
+ byte Flags = (byte) 0x08;
+ vxLANHeader[0] = Flags;
+
+ // Extract the serviceId details and imprint on the VxLAN Header
+ vxLANHeader[4] = (byte) (serviceId >> 16);
+ vxLANHeader[5] = (byte) (serviceId >> 8);
+ vxLANHeader[6] = (byte) (serviceId >> 0);
+
+ // Matching metadata
+// mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {
+// new BigInteger(1, vxLANHeader),
+// MetaDataUtil.METADA_MASK_VALID_TUNNEL_ID_BIT_AND_TUNNEL_ID }));
+
+ Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
+ getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE,serviceId), 5, String.format("%s:%d","ITM Flow Entry ",serviceId),
+ 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(serviceId)),mkMatches, input.getInstruction());
+
+ ListenableFuture<Void> installFlowResult = mdsalManager.installFlow(input.getDpnId(), terminatingServiceTableFlow);
+ Futures.addCallback(installFlowResult, new FutureCallback<Void>(){
+
+ @Override
+ public void onSuccess(Void aVoid) {
+ result.set(RpcResultBuilder.<Void>success().build());
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ String msg = String.format("Unable to install terminating service flow for %s", input.getDpnId());
+ LOG.error("create terminating service actions failed. {}. {}", msg, error);
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
+ }
+ });
+ // result.set(RpcResultBuilder.<Void>success().build());
+ return result;
+ }
+
+ @Override
+ public Future<RpcResult<java.lang.Void>> removeTerminatingServiceActions(final RemoveTerminatingServiceActionsInput input) {
+ LOG.info("remove terminatingServiceActions called with DpnId = {} and serviceId = {}", input.getDpnId(), input.getServiceId());
+ final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+ Flow terminatingServiceTableFlow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
+ getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE,input.getServiceId()), 5, String.format("%s:%d","ITM Flow Entry ",input.getServiceId()),
+ 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(input.getServiceId())),getTunnelMatchesForServiceId(input.getServiceId()), null );
+
+ ListenableFuture<Void> installFlowResult = mdsalManager.removeFlow(input.getDpnId(), terminatingServiceTableFlow);
+ Futures.addCallback(installFlowResult, new FutureCallback<Void>(){
+
+ @Override
+ public void onSuccess(Void aVoid) {
+ result.set(RpcResultBuilder.<Void>success().build());
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ String msg = String.format("Unable to remove terminating service flow for %s", input.getDpnId());
+ LOG.error("remove terminating service actions failed. {}. {}", msg, error);
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
+ }
+ });
+ //result.set(RpcResultBuilder.<Void>success().build());
+
+ return result ;
+ }
+
+
+ public List<MatchInfo> getTunnelMatchesForServiceId(int serviceId) {
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ byte[] vxLANHeader = new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+ // Flags Byte
+ byte Flags = (byte) 0x08;
+ vxLANHeader[0] = Flags;
+
+ // Extract the serviceId details and imprint on the VxLAN Header
+ vxLANHeader[4] = (byte) (serviceId >> 16);
+ vxLANHeader[5] = (byte) (serviceId >> 8);
+ vxLANHeader[6] = (byte) (serviceId >> 0);
+
+ // Matching metadata
+ mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[]{
+ BigInteger.valueOf(serviceId)}));
+
+ return mkMatches;
+ }
+
+ private String getFlowRef(long termSvcTable, int svcId) {
+ return new StringBuffer().append(termSvcTable).append(svcId).toString();
+ }
+
+ @Override
+ public Future<RpcResult<GetInternalOrExternalInterfaceNameOutput>> getInternalOrExternalInterfaceName(
+ GetInternalOrExternalInterfaceNameInput input) {
+ RpcResultBuilder<GetInternalOrExternalInterfaceNameOutput> resultBld = RpcResultBuilder.failed();
+ BigInteger srcDpn = input.getSourceDpid() ;
+ String srcNode = srcDpn.toString();
+ IpAddress dstIp = input.getDestinationIp() ;
+ InstanceIdentifier<ExternalTunnel> path1 = InstanceIdentifier.create(
+ ExternalTunnelList.class)
+ .child(ExternalTunnel.class, new ExternalTunnelKey(String.valueOf(dstIp), srcDpn.toString(), TunnelTypeMplsOverGre.class));
+
+ Optional<ExternalTunnel> ext = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path1, dataBroker);
+
+ if( ext != null && ext.isPresent())
+ {
+ ExternalTunnel extTunnel = ext.get();
+ GetInternalOrExternalInterfaceNameOutputBuilder output = new GetInternalOrExternalInterfaceNameOutputBuilder().setInterfaceName(extTunnel.getTunnelInterfaceName() );
+ resultBld = RpcResultBuilder.success();
+ resultBld.withResult(output.build()) ;
+ } else {
+ List<DPNTEPsInfo> meshedDpnList = ItmUtils.getTunnelMeshInfo(dataBroker);
+ // Look for external tunnels if not look for internal tunnel
+ for (DPNTEPsInfo teps : meshedDpnList) {
+ TunnelEndPoints firstEndPt = teps.getTunnelEndPoints().get(0);
+ if (dstIp.equals(firstEndPt.getIpAddress())) {
+ InstanceIdentifier<InternalTunnel> path = InstanceIdentifier.create(
+ TunnelList.class)
+ .child(InternalTunnel.class, new InternalTunnelKey(teps.getDPNID(), srcDpn, input.getTunnelType()));
+
+ Optional<InternalTunnel>
+ tnl =
+ ItmUtils.read(LogicalDatastoreType.CONFIGURATION, path, dataBroker);
+ if (tnl != null && tnl.isPresent()) {
+ InternalTunnel tunnel = tnl.get();
+ GetInternalOrExternalInterfaceNameOutputBuilder
+ output =
+ new GetInternalOrExternalInterfaceNameOutputBuilder()
+ .setInterfaceName(tunnel.getTunnelInterfaceName());
+ resultBld = RpcResultBuilder.success();
+ resultBld.withResult(output.build());
+ break;
+ }
+ }
+ }
+ }
+ return Futures.immediateFuture(resultBld.build());
+ }
+
+ @Override
+ public Future<RpcResult<java.lang.Void>> deleteL2GwDevice(DeleteL2GwDeviceInput input) {
+ final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+ try {
+ final IpAddress hwIp = input.getIpAddress();
+ final String node_id = input.getNodeId();
+ InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
+ Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, containerPath, dataBroker);
+ if (tZonesOptional.isPresent()) {
+ TransportZones tZones = tZonesOptional.get();
+ if (tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty()) {
+ LOG.error("No teps configured");
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
+ return result;
+ }
+ String transportZone = tZones.getTransportZone().get(0).getZoneName();
+ if (tZones.getTransportZone().get(0).getSubnets() == null || tZones.getTransportZone().get(0).getSubnets().isEmpty()) {
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
+ return result;
+ }
+ SubnetsKey subnetsKey = tZones.getTransportZone().get(0).getSubnets().get(0).getKey();
+ DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, node_id);
+ InstanceIdentifier<DeviceVteps> path =
+ InstanceIdentifier.builder(TransportZones.class)
+ .child(TransportZone.class, new TransportZoneKey(transportZone))
+ .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey).build();
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ //TO DO: add retry if it fails
+ t.delete(LogicalDatastoreType.CONFIGURATION, path);
+
+ ListenableFuture<Void> futureCheck = t.submit();
+ Futures.addCallback(futureCheck, new FutureCallback<Void>() {
+
+ @Override
+ public void onSuccess(Void aVoid) {
+ result.set(RpcResultBuilder.<Void>success().build());
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ String msg = String.format("Unable to write HwVtep {} to datastore", node_id);
+ LOG.error("Unable to write HwVtep {}, {} to datastore", node_id , hwIp);
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
+ }
+ });
+ }
+ return result;
+ } catch (Exception e) {
+ RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed().
+ withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e);
+ return Futures.immediateFuture(resultBuilder.build());
+ }
+ }
+
+ @Override
+ public Future<RpcResult<java.lang.Void>> addL2GwDevice(AddL2GwDeviceInput input) {
+
+ final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+ try {
+ final IpAddress hwIp = input.getIpAddress();
+ final String node_id = input.getNodeId();
+ InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
+ Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, containerPath, dataBroker);
+ if (tZonesOptional.isPresent()) {
+ TransportZones tZones = tZonesOptional.get();
+ if (tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty()) {
+ LOG.error("No teps configured");
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
+ return result;
+ }
+ String transportZone = tZones.getTransportZone().get(0).getZoneName();
+ if (tZones.getTransportZone().get(0).getSubnets() == null || tZones.getTransportZone().get(0).getSubnets().isEmpty()) {
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
+ return result;
+ }
+ SubnetsKey subnetsKey = tZones.getTransportZone().get(0).getSubnets().get(0).getKey();
+ DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, node_id);
+ InstanceIdentifier<DeviceVteps> path =
+ InstanceIdentifier.builder(TransportZones.class)
+ .child(TransportZone.class, new TransportZoneKey(transportZone))
+ .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey).build();
+ DeviceVteps deviceVtep = new DeviceVtepsBuilder().setKey(deviceVtepKey).setIpAddress(hwIp).setNodeId(
+ node_id).setTopologyId(input.getTopologyId()).build();
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ //TO DO: add retry if it fails
+ t.put(LogicalDatastoreType.CONFIGURATION, path, deviceVtep, true);
+
+ ListenableFuture<Void> futureCheck = t.submit();
+ Futures.addCallback(futureCheck, new FutureCallback<Void>() {
+
+ @Override
+ public void onSuccess(Void aVoid) {
+ result.set(RpcResultBuilder.<Void>success().build());
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ String msg = String.format("Unable to write HwVtep {} to datastore", node_id);
+ LOG.error("Unable to write HwVtep {}, {} to datastore", node_id , hwIp);
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
+ }
+ });
+ }
+ else {
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No TransportZones configured").build());
+ return result;
+ }
+ return result;
+ } catch (Exception e) {
+ RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed().
+ withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
+ return Futures.immediateFuture(resultBuilder.build());
+ }
+ }
+
+ @Override
+ public Future<RpcResult<java.lang.Void>> addL2GwMlagDevice(AddL2GwMlagDeviceInput input)
+ {
+ final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+ try {
+ final IpAddress hwIp = input.getIpAddress();
+ final List<String> node_id = input.getNodeId();
+ InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
+ Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, containerPath, dataBroker);
+ if (tZonesOptional.isPresent()) {
+ TransportZones tZones = tZonesOptional.get();
+ if (tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty()) {
+ LOG.error("No teps configured");
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
+ return result;
+ }
+ String transportZone = tZones.getTransportZone().get(0).getZoneName();
+ if (tZones.getTransportZone().get(0).getSubnets() == null || tZones.getTransportZone().get(0).getSubnets().isEmpty()) {
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
+ return result;
+ }
+ SubnetsKey subnetsKey = tZones.getTransportZone().get(0).getSubnets().get(0).getKey();
+ DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, node_id.get(0));
+ InstanceIdentifier<DeviceVteps> path =
+ InstanceIdentifier.builder(TransportZones.class)
+ .child(TransportZone.class, new TransportZoneKey(transportZone))
+ .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey).build();
+ DeviceVteps deviceVtep = new DeviceVtepsBuilder().setKey(deviceVtepKey).setIpAddress(hwIp).setNodeId(node_id.get(0)).setTopologyId(input.getTopologyId()).build();
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ LOG.trace("writing hWvtep{}",deviceVtep);
+ t.put(LogicalDatastoreType.CONFIGURATION, path, deviceVtep, true);
+ if(node_id.size() == 2) {
+ LOG.trace("second node-id {}",node_id.get(1));
+ DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, node_id.get(1));
+ InstanceIdentifier<DeviceVteps> path2 = InstanceIdentifier.builder(TransportZones.class)
+ .child(TransportZone.class, new TransportZoneKey(transportZone))
+ .child(Subnets.class, subnetsKey).child(DeviceVteps.class, deviceVtepKey2).build();
+ DeviceVteps deviceVtep2 = new DeviceVtepsBuilder().setKey(deviceVtepKey2).setIpAddress(hwIp).setNodeId(node_id.get(1))
+ .setTopologyId(input.getTopologyId()).build();
+ LOG.trace("writing {}",deviceVtep2);
+ t.put(LogicalDatastoreType.CONFIGURATION, path2, deviceVtep2, true);
+ }ListenableFuture<Void> futureCheck = t.submit();
+ Futures.addCallback(futureCheck, new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(Void aVoid) {
+ result.set(RpcResultBuilder.<Void>success().build());
+ }
+ @Override
+ public void onFailure(Throwable error) {
+ String msg = String.format("Unable to write HwVtep {} to datastore", node_id);
+ LOG.error("Unable to write HwVtep {}, {} to datastore", node_id , hwIp);
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
+ }
+ });
+ }
+ return result;
+ } catch (Exception e) {
+ RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed().
+ withError(RpcError.ErrorType.APPLICATION, "Adding l2 Gateway to DS Failed", e);
+ return Futures.immediateFuture(resultBuilder.build());
+ }
+ }
+ @Override
+ public Future<RpcResult<Void>> deleteL2GwMlagDevice(DeleteL2GwMlagDeviceInput input) {
+ final SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+ try {
+ final IpAddress hwIp = input.getIpAddress();
+ final List<String> node_id = input.getNodeId();
+ InstanceIdentifier<TransportZones> containerPath = InstanceIdentifier.create(TransportZones.class);
+ Optional<TransportZones> tZonesOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, containerPath, dataBroker);
+ if (tZonesOptional.isPresent()) {
+ TransportZones tZones = tZonesOptional.get();
+ if (tZones.getTransportZone() == null || tZones.getTransportZone().isEmpty()) {
+ LOG.error("No teps configured");
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No teps Configured").build());
+ return result;
+ }
+ String transportZone = tZones.getTransportZone().get(0).getZoneName();
+ if (tZones.getTransportZone().get(0).getSubnets() == null || tZones.getTransportZone().get(0).getSubnets().isEmpty()) {
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, "No subnets Configured").build());
+ return result;
+ }
+ SubnetsKey subnetsKey = tZones.getTransportZone().get(0).getSubnets().get(0).getKey();
+ DeviceVtepsKey deviceVtepKey = new DeviceVtepsKey(hwIp, node_id.get(0));
+ InstanceIdentifier<DeviceVteps> path =
+ InstanceIdentifier.builder(TransportZones.class)
+ .child(TransportZone.class, new TransportZoneKey(transportZone))
+ .child(Subnets.class, subnetsKey).child(DeviceVteps.class,
+ deviceVtepKey).build();
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ t.delete(LogicalDatastoreType.CONFIGURATION, path);
+ DeviceVtepsKey deviceVtepKey2 = new DeviceVtepsKey(hwIp, node_id.get(1));
+ InstanceIdentifier<DeviceVteps> path2 =
+ InstanceIdentifier.builder(TransportZones.class)
+ .child(TransportZone.class, new TransportZoneKey(transportZone))
+ .child(Subnets.class, subnetsKey).child(DeviceVteps.class,
+ deviceVtepKey2).build();
+ t.delete(LogicalDatastoreType.CONFIGURATION, path2);
+ ListenableFuture<Void> futureCheck = t.submit();
+ Futures.addCallback(futureCheck, new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(Void aVoid) {
+ result.set(RpcResultBuilder.<Void>success().build());
+ }
+ @Override
+ public void onFailure(Throwable error) {
+ String msg = String.format("Unable to write HwVtep {} to datastore", node_id);
+ LOG.error("Unable to write HwVtep {}, {} to datastore", node_id , hwIp);
+ result.set(RpcResultBuilder.<Void>failed().withError(RpcError.ErrorType.APPLICATION, msg, error).build());
+ }
+ });
+ }
+ return result;
+ } catch (Exception e) {
+ RpcResultBuilder<java.lang.Void> resultBuilder = RpcResultBuilder.<Void>failed().
+ withError(RpcError.ErrorType.APPLICATION, "Deleting l2 Gateway to DS Failed", e);
+ return Futures.immediateFuture(resultBuilder.build());
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.itm.snd;
+
+import java.lang.management.ManagementFactory;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ITMStatusMonitor implements ITMStatusMonitorMBean {
+
+
+ private String serviceStatus;
+ private static ITMStatusMonitor itmStatusMonitor = new ITMStatusMonitor();
+ private static final String JMX_ITM_OBJ_NAME = "com.ericsson.sdncp.services.status:type=SvcItmService";
+ private static final Logger log = LoggerFactory.getLogger(ITMStatusMonitor.class);
+
+ private ITMStatusMonitor () {
+ }
+
+ public void registerMbean() {
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+ try {
+ ObjectName objName = new ObjectName(JMX_ITM_OBJ_NAME);
+ mbs.registerMBean(itmStatusMonitor, objName);
+ log.info("itm MXBean registration SUCCESSFUL!!! {}", JMX_ITM_OBJ_NAME);
+ } catch (InstanceAlreadyExistsException iaeEx) {
+ log.error("itm MXBean registration FAILED with InstanceAlreadyExistsException", iaeEx);
+ } catch (MBeanRegistrationException mbrEx) {
+ log.error("itm MXBean registration FAILED with MBeanRegistrationException", mbrEx);
+ } catch (NotCompliantMBeanException ncmbEx) {
+ log.error("itm MXBean registration FAILED with NotCompliantMBeanException", ncmbEx);
+ } catch (MalformedObjectNameException monEx) {
+ log.error("itm MXBean registration failed with MalformedObjectNameException", monEx);
+ }
+ }
+
+ public static ITMStatusMonitor getInstance() {
+ return itmStatusMonitor;
+ }
+
+ @Override
+ public String acquireServiceStatus() {
+ return serviceStatus;
+ }
+
+ public void reportStatus (String serviceStatus) {
+ this.serviceStatus = serviceStatus;
+ }
+
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.itm.snd;
+
+public interface ITMStatusMonitorMBean {
+
+ public String acquireServiceStatus();
+
+}
--- /dev/null
+package org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.impl.rev141210;
+
+import org.opendaylight.vpnservice.itm.impl.ItmProvider;
+public class ItmModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.impl.rev141210.AbstractItmModule {
+ public ItmModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public ItmModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.impl.rev141210.ItmModule 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() {
+ ItmProvider provider = new ItmProvider();
+ provider.setMdsalApiManager(getMdsalutilDependency());
+ provider.setNotificationPublishService(getNotificationPublishServiceDependency());
+ provider.setNotificationService(getNotificationServiceDependency());
+ provider.setRpcProviderRegistry(getRpcregistryDependency());
+ getBrokerDependency().registerProvider(provider);
+ return provider;
+ }
+
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: itm-impl yang module local name: itm
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Mon Jan 04 14:02:13 IST 2016
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.impl.rev141210;
+public class ItmModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.impl.rev141210.AbstractItmModuleFactory {
+
+}
--- /dev/null
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+ <reference id="itmProviderRef" interface="org.opendaylight.vpnservice.itm.api.IITMProvider" availability="optional" />
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+ <command>
+ <action class="org.opendaylight.vpnservice.itm.cli.TepAdd">
+ <property name="itmProvider" ref="itmProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.itm.cli.TepDelete">
+ <property name="itmProvider" ref="itmProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.itm.cli.TepShow">
+ <property name="itmProvider" ref="itmProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.itm.cli.TepCommit">
+ <property name="itmProvider" ref="itmProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.itm.cli.TepShowState">
+ <property name="itmProvider" ref="itmProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.itm.cli.TepConfigureTunnelType">
+ <property name="itmProvider" ref="itmProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.itm.cli.TepMonitor">
+ <property name="itmProvider" ref="itmProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.itm.cli.TepDeleteDatastore">
+ <property name="itmProvider" ref="itmProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.itm.cli.VtepSchemaAdd">
+ <property name="itmProvider" ref="itmProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.itm.cli.VtepSchemaShow">
+ <property name="itmProvider" ref="itmProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.itm.cli.VtepSchemaUpdate">
+ <property name="itmProvider" ref="itmProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.itm.cli.VtepSchemaDelete">
+ <property name="itmProvider" ref="itmProviderRef" />
+ </action>
+ </command>
+ <command>
+ <action class="org.opendaylight.vpnservice.itm.cli.TepEnableTunnelMonitor">
+ <property name="itmProvider" ref="itmProviderRef" />
+ </action>
+ </command>
+ </command-bundle>
+</blueprint>
\ No newline at end of file
--- /dev/null
+module itm-impl {
+ yang-version 1;
+ namespace "urn:opendaylight:vpnservice:itm:impl";
+ prefix "itm-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 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 itm project";
+
+ revision "2014-12-10" {
+ description
+ "Initial revision";
+ }
+
+ identity itm {
+ base config:module-type;
+ config:provided-service itm:itm;
+ config:java-name-prefix Itm;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case itm {
+ when "/config:modules/config:module/config:type = 'itm'";
+ container broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-broker-osgi-registry;
+ }
+ }
+ }
+ container odlinterface {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity odlif:odl-interface;
+ }
+ }
+ }
+ container mdsalutil {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity odl-mdsal:odl-mdsalutil;
+ }
+ }
+ }
+ container notification-publish-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding-impl:binding-new-notification-publish-service;
+ }
+ }
+ }
+ container rpcregistry {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-rpc-registry;
+ }
+ }
+ }
+ container notification-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding-impl:binding-new-notification-service;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. 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.itm.impl;
+
+import org.junit.Test;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.vpnservice.itm.impl.ItmProvider;
+
+import static org.mockito.Mockito.mock;
+
+public class ItmProviderTest {
+ @Test
+ public void testOnSessionInitiated() {
+ ItmProvider provider = new ItmProvider();
+
+ // ensure no exceptions
+ // currently this method is empty
+ provider.onSessionInitiated(mock(BindingAwareBroker.ProviderContext.class));
+ }
+
+ @Test
+ public void testClose() throws Exception {
+ ItmProvider provider = new ItmProvider();
+
+ // ensure no exceptions
+ // currently this method is empty
+ provider.close();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. 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.yang.gen.v1.urn.opendaylight.vpnservice.itm.impl.rev141210;
+
+import org.junit.Test;
+
+public class ItmModuleFactoryTest {
+ @Test
+ public void testFactoryConstructor() {
+ // ensure no exceptions on construction
+ new ItmModuleFactory();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. 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.yang.gen.v1.urn.opendaylight.vpnservice.itm.impl.rev141210;
+
+import org.junit.Test;
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.JmxAttribute;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.vpnservice.itm.impl.ItmProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.impl.rev141210.ItmModule;
+
+import javax.management.ObjectName;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class ItmModuleTest {
+ @Test
+ public void testCustomValidation() {
+ ItmModule module = new ItmModule(mock(ModuleIdentifier.class), mock(DependencyResolver.class));
+
+ // ensure no exceptions on validation
+ // currently this method is empty
+ module.customValidation();
+ }
+
+ @Test
+ public void testCreateInstance() throws Exception {
+ // configure mocks
+ DependencyResolver dependencyResolver = mock(DependencyResolver.class);
+ BindingAwareBroker broker = mock(BindingAwareBroker.class);
+ when(dependencyResolver.resolveInstance(eq(BindingAwareBroker.class), any(ObjectName.class), any(JmxAttribute.class))).thenReturn(broker);
+
+ // create instance of module with injected mocks
+ ItmModule module = new ItmModule(mock(ModuleIdentifier.class), dependencyResolver);
+
+ // getInstance calls resolveInstance to get the broker dependency and then calls createInstance
+ AutoCloseable closeable = module.getInstance();
+
+ // verify that the module registered the returned provider with the broker
+ verify(broker).registerProvider((ItmProvider)closeable);
+
+ // ensure no exceptions on close
+ closeable.close();
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>itm-aggregator</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <name>itm</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>itm-api</module>
+ <module>itm-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>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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>binding-parent</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/binding-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>lockmanager-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.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+ </dependencies>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>
+ org.opendaylight.yangtools
+ </groupId>
+ <artifactId>
+ yang-maven-plugin
+ </artifactId>
+ <versionRange>
+ [0.8.0-SNAPSHOT,)
+ </versionRange>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
--- /dev/null
+module lock-manager {
+ namespace "urn:opendaylight:vpnservice:lockmanager";
+ prefix lockmgr;
+
+ revision "2015-08-19" {
+ description "YANG model describes methods that ensure locking while accessing the datastore";
+ }
+
+ typedef time-units {
+ type enumeration {
+ enum days;
+ enum hours;
+ enum microseconds;
+ enum milliseconds;
+ enum minutes;
+ enum nanoseconds;
+ enum seconds;
+ }
+ }
+
+ container locks {
+ description "Holds the list of lock name and lock owner";
+ list lock {
+ key "lock-name";
+ leaf lock-name {
+ type string;
+ mandatory true;
+ }
+ leaf lock-owner {
+ type string;
+ mandatory true;
+ }
+ }
+ }
+
+ rpc lock {
+ description "Method that checks if its locked already. If not adds the lock to the list of locks. Else tries until it acquires the lock";
+ input {
+ leaf lock-name {
+ type string;
+ mandatory true;
+ }
+ }
+ }
+
+ rpc try-lock {
+ description "Method that checks if its locked already. If not adds the lock to the list of locks. Else tries for the specified time";
+ input {
+ leaf lock-name {
+ type string;
+ mandatory true;
+ }
+ leaf time {
+ type uint32;
+ }
+ leaf time-unit {
+ type time-units;
+ }
+ }
+ }
+
+ rpc unlock {
+ description "Method that removes the lock from the list of locks";
+ input {
+ leaf lock-name {
+ type string;
+ mandatory true;
+ }
+ }
+ }
+}
\ 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) 2015 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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>lockmanager-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>lockmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>
+ org.opendaylight.yangtools
+ </groupId>
+ <artifactId>
+ yang-maven-plugin
+ </artifactId>
+ <versionRange>
+ [0.8.0-SNAPSHOT,)
+ </versionRange>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.jacoco</groupId>
+ <artifactId>
+ jacoco-maven-plugin
+ </artifactId>
+ <versionRange>
+ [0.7.2.201409121644,)
+ </versionRange>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
\ 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) 2015 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:lockmanager:impl?module=lockmanager-impl&revision=2015-08-19</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</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:lockmanager:impl">prefix:lockmanager-impl</type>
+ <name>lockmanager-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>
+ <rpc-registry>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+ <name>binding-rpc-broker</name>
+ </rpc-registry>
+ </module>
+ </modules>
+ </data>
+ </configuration>
+</snapshot>
--- /dev/null
+/*
+ * Copyright (c) 2015 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.lockmanager;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.TryLockInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.UnlockInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.locks.Lock;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+
+public class LockManager implements LockManagerService {
+ private static final Logger LOG = LoggerFactory.getLogger(LockManager.class);
+
+ private static final int DEFAULT_RETRY_COUNT = 3;
+ private static final int DEFAULT_WAIT_TIME_IN_MILLIS = 1000;
+
+ private final DataBroker broker;
+
+ public LockManager(final DataBroker db) {
+ broker = db;
+ }
+
+ @Override
+ public Future<RpcResult<Void>> lock(LockInput input) {
+ String lockName = input.getLockName();
+ LOG.info("Locking {}" , lockName);
+ InstanceIdentifier<Lock> lockInstanceIdentifier = LockManagerUtils.getLockInstanceIdentifier(lockName);
+ Lock lockData = LockManagerUtils.buildLockData(lockName);
+ try {
+ getLock(lockInstanceIdentifier, lockData);
+ RpcResultBuilder<Void> lockRpcBuilder = RpcResultBuilder.success();
+ LOG.info("Acquired lock {}" , lockName);
+ return Futures.immediateFuture(lockRpcBuilder.build());
+ } catch (InterruptedException e) {
+ RpcResultBuilder<Void> lockRpcBuilder = RpcResultBuilder.failed();
+ LOG.info("Failed to get lock {}" , lockName);
+ return Futures.immediateFuture(lockRpcBuilder.build());
+ }
+ }
+
+ @Override
+ public Future<RpcResult<Void>> tryLock(TryLockInput input) {
+ String lockName = input.getLockName();
+ LOG.info("Locking {}" , lockName);
+ long waitTime = input.getTime() == null ? DEFAULT_WAIT_TIME_IN_MILLIS * DEFAULT_RETRY_COUNT : input.getTime();
+ TimeUnit timeUnit = (TimeUnit) (input.getTimeUnit() == null ? TimeUnit.MILLISECONDS: LockManagerUtils.convertToTimeUnit(input.getTimeUnit()));
+ waitTime = LockManagerUtils.convertToMillis(waitTime, timeUnit);
+ long retryCount = waitTime / DEFAULT_WAIT_TIME_IN_MILLIS;
+ InstanceIdentifier<Lock> lockInstanceIdentifier = LockManagerUtils.getLockInstanceIdentifier(lockName);
+ Lock lockData = LockManagerUtils.buildLockData(lockName);
+ try {
+ if (getLock(lockInstanceIdentifier, lockData, retryCount)) {
+ RpcResultBuilder<Void> lockRpcBuilder = RpcResultBuilder.success();
+ LOG.info("Acquired lock {}" , lockName);
+ return Futures.immediateFuture(lockRpcBuilder.build());
+ }
+ RpcResultBuilder<Void> lockRpcBuilder = RpcResultBuilder.failed();
+ LOG.info("Failed to get lock {}" , lockName);
+ return Futures.immediateFuture(lockRpcBuilder.build());
+ } catch (Exception e) {
+ RpcResultBuilder<Void> lockRpcBuilder = RpcResultBuilder.failed();
+ LOG.info("Failed to get lock {}" , lockName);
+ return Futures.immediateFuture(lockRpcBuilder.build());
+ }
+ }
+
+ @Override
+ public Future<RpcResult<Void>> unlock(UnlockInput input) {
+ String lockName = input.getLockName();
+ LOG.info("Unlocking {}" , lockName);
+ InstanceIdentifier<Lock> lockInstanceIdentifier = LockManagerUtils.getLockInstanceIdentifier(lockName);
+ unlock(lockName, lockInstanceIdentifier);
+ RpcResultBuilder<Void> lockRpcBuilder = RpcResultBuilder.success();
+ return Futures.immediateFuture(lockRpcBuilder.build());
+ }
+
+ /**
+ * Try to acquire lock indefinitely until it is successful.
+ * @param lockInstanceIdentifier
+ * @param lockData
+ */
+ private void getLock(final InstanceIdentifier<Lock> lockInstanceIdentifier, final Lock lockData) throws InterruptedException {
+ try {
+ if (!readWriteLock(lockInstanceIdentifier, lockData)) {
+ LOG.debug("Already locked trying after {}", DEFAULT_WAIT_TIME_IN_MILLIS);
+ LockManagerUtils.sleep(DEFAULT_WAIT_TIME_IN_MILLIS);
+ getLock(lockInstanceIdentifier, lockData);
+ }
+ } catch (ExecutionException e) {
+ LOG.error("In getLock unable to get lock due to {}, trying again", e.getMessage());
+ LockManagerUtils.sleep(DEFAULT_WAIT_TIME_IN_MILLIS);
+ getLock(lockInstanceIdentifier, lockData);
+ }
+ }
+
+ /**
+ * Try to acquire lock for mentioned retryCount. Returns true if successfully acquired lock.
+ * @param lockInstanceIdentifier
+ * @param lockData
+ * @param retryCount
+ * @return
+ * @throws InterruptedException
+ */
+ private boolean getLock(InstanceIdentifier<Lock> lockInstanceIdentifier,
+ Lock lockData, long retryCount) throws InterruptedException {
+ if (retryCount < 0) {
+ return false;
+ }
+ try {
+ if (!readWriteLock(lockInstanceIdentifier, lockData)) {
+ LOG.debug("Already locked trying after {}, retry value {}", DEFAULT_WAIT_TIME_IN_MILLIS, retryCount);
+ LockManagerUtils.sleep(DEFAULT_WAIT_TIME_IN_MILLIS);
+ return getLock(lockInstanceIdentifier, lockData, retryCount - 1);
+ }
+ } catch (ExecutionException e) {
+ LOG.error("In getLock unable to get lock due to {}, trying again, retry value {}", e.getMessage(), retryCount);
+ LockManagerUtils.sleep(DEFAULT_WAIT_TIME_IN_MILLIS);
+ return getLock(lockInstanceIdentifier, lockData, retryCount - 1);
+ }
+ return true;
+ }
+
+ /**
+ * Read and write the lock immediately if available. Returns true if successfully locked.
+ * @param lockInstanceIdentifier
+ * @param lockData
+ * @return
+ * @throws InterruptedException
+ * @throws ExecutionException
+ */
+ private boolean readWriteLock (final InstanceIdentifier<Lock> lockInstanceIdentifier, final Lock lockData) throws InterruptedException, ExecutionException {
+ ReadWriteTransaction tx = broker.newReadWriteTransaction();
+ Optional<Lock> result = Optional.absent();
+ result = tx.read(LogicalDatastoreType.OPERATIONAL, lockInstanceIdentifier).get();
+ if (!result.isPresent()) {
+ tx.put(LogicalDatastoreType.OPERATIONAL, lockInstanceIdentifier, lockData, true);
+ CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+ futures.get();
+ return true;
+ }
+ if (result.get().getLockOwner() == Thread.currentThread().getName()) {
+ return true;
+ }
+ return false;
+ }
+
+ private void unlock(final String lockName, final InstanceIdentifier<Lock> lockInstanceIdentifier) {
+ ReadWriteTransaction tx = broker.newReadWriteTransaction();
+ Optional<Lock> result = Optional.absent();
+ try {
+ result = tx.read(LogicalDatastoreType.OPERATIONAL, lockInstanceIdentifier).get();
+ if (!result.isPresent()) {
+ LOG.info("{} is already unlocked", lockName);
+ return;
+ }
+ tx.delete(LogicalDatastoreType.OPERATIONAL, lockInstanceIdentifier);
+ CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+ futures.get();
+ } catch (Exception e) {
+ LOG.error("In unlock unable to unlock due to {}", e.getMessage());
+ }
+ }
+
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.lockmanager;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+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.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class LockManagerServiceProvider implements BindingAwareProvider,
+ AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(LockManagerServiceProvider.class);
+ private LockManager lockManager;
+ private RpcProviderRegistry rpcProviderRegistry;
+
+ public RpcProviderRegistry getRpcProviderRegistry() {
+ return rpcProviderRegistry;
+ }
+
+ public void setRpcProviderRegistry(RpcProviderRegistry rpcProviderRegistry) {
+ this.rpcProviderRegistry = rpcProviderRegistry;
+ }
+
+ @Override
+ public void onSessionInitiated(ProviderContext session){
+ LOG.info("LockManagerServiceProvider Session Initiated");
+ try {
+ final DataBroker dataBroker = session.getSALService(DataBroker.class);
+ lockManager = new LockManager(dataBroker);
+ final BindingAwareBroker.RpcRegistration<LockManagerService> rpcRegistration = getRpcProviderRegistry().addRpcImplementation(LockManagerService.class, lockManager);
+ } catch (Exception e) {
+ LOG.error("Error initializing services", e);
+ }
+ }
+
+ public LockManagerServiceProvider(RpcProviderRegistry rpcRegistry) {
+ this.rpcProviderRegistry = rpcRegistry;
+ }
+
+ @Override
+ public void close() throws Exception {
+ }
+ }
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.lockmanager;
+
+import java.util.concurrent.TimeUnit;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.Locks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.TimeUnits;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.locks.Lock;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.locks.LockBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.locks.LockKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class LockManagerUtils {
+
+ public static long convertToMillis(long waitTime, TimeUnit timeUnit) {
+ return timeUnit.toMillis(waitTime);
+ }
+
+ public static void sleep(long waitTime) {
+ try {
+ Thread.sleep(waitTime);
+ } catch (InterruptedException exception) {
+ }
+ }
+
+ public static TimeUnit convertToTimeUnit(TimeUnits timeUnit) {
+ switch (timeUnit) {
+ case Days:
+ return TimeUnit.DAYS;
+ case Microseconds:
+ return TimeUnit.MICROSECONDS;
+ case Hours:
+ return TimeUnit.HOURS;
+ case Minutes:
+ return TimeUnit.MINUTES;
+ case Nanoseconds:
+ return TimeUnit.NANOSECONDS;
+ case Seconds:
+ return TimeUnit.SECONDS;
+ case Milliseconds:
+ default:
+ return TimeUnit.MILLISECONDS;
+ }
+ }
+
+ public static InstanceIdentifier<Lock> getLockInstanceIdentifier(String lockName) {
+ return InstanceIdentifier
+ .builder(Locks.class).child(Lock.class,
+ new LockKey(lockName)).build();
+ }
+
+ public static Lock buildLockData(String lockName) {
+ return new LockBuilder().setKey(new LockKey(lockName)).setLockName(lockName).setLockOwner(Thread.currentThread().getName()).build();
+ }
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lockmanager.impl.rev150819;
+
+import org.opendaylight.lockmanager.LockManagerServiceProvider;
+
+public class LockManagerImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lockmanager.impl.rev150819.AbstractLockManagerImplModule {
+ public LockManagerImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public LockManagerImplModule(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.lockmanager.impl.rev150819.LockManagerImplModule 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() {
+ LockManagerServiceProvider provider = new LockManagerServiceProvider(getRpcRegistryDependency());
+ getBrokerDependency().registerProvider(provider);
+ return provider;
+ }
+
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: lockmanager-impl yang module local name: lockmanager-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Thu Aug 27 12:50:22 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.lockmanager.impl.rev150819;
+public class LockManagerImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lockmanager.impl.rev150819.AbstractLockManagerImplModuleFactory {
+
+}
--- /dev/null
+module lockmanager-impl {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:lockmanager:impl";
+ prefix "lockmanager-impl";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
+
+ description
+ "Service definition for lockmanager project";
+
+ revision "2015-08-19" {
+ description
+ "Initial revision";
+ }
+
+ identity lockmanager-impl {
+ base config:module-type;
+ config:java-name-prefix LockManagerImpl;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case lockmanager-impl {
+ when "/config:modules/config:module/config:type = 'lockmanager-impl'";
+ container broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-broker-osgi-registry;
+ }
+ }
+ }
+ container rpc-registry {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-rpc-registry;
+ }
+ }
+ }
+
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>lockmanager-aggregator</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <name>lockmanager</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>lockmanager-api</module>
+ <module>lockmanager-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>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>mdsalutil-api</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.model</groupId>
+ <artifactId>model-flow-base</artifactId>
+ <version>${openflowplugin.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.model</groupId>
+ <artifactId>model-flow-service</artifactId>
+ <version>${openflowplugin.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <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>
+ <dependency>
+ <groupId>org.opendaylight.ovsdb</groupId>
+ <artifactId>hwvtepsouthbound-api</artifactId>
+ <version>${vpns.ovsdb.version}</version>
+ </dependency>
+
+ </dependencies>
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2015 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.datastoreutils;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.*;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+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.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+public abstract class AsyncClusteredDataChangeListenerBase<T extends DataObject, K extends ClusteredDataChangeListener> implements ClusteredDataChangeListener, AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(AsyncClusteredDataChangeListenerBase.class);
+
+ private static final int DATATREE_CHANGE_HANDLER_THREAD_POOL_CORE_SIZE = 1;
+ private static final int DATATREE_CHANGE_HANDLER_THREAD_POOL_MAX_SIZE = 1;
+ private static final int DATATREE_CHANGE_HANDLER_THREAD_POOL_KEEP_ALIVE_TIME_SECS = 300;
+ private static final int STARTUP_LOOP_TICK = 500;
+ private static final int STARTUP_LOOP_MAX_RETRIES = 8;
+
+ private static ThreadPoolExecutor dataChangeHandlerExecutor = new ThreadPoolExecutor(
+ DATATREE_CHANGE_HANDLER_THREAD_POOL_CORE_SIZE,
+ DATATREE_CHANGE_HANDLER_THREAD_POOL_MAX_SIZE,
+ DATATREE_CHANGE_HANDLER_THREAD_POOL_KEEP_ALIVE_TIME_SECS,
+ TimeUnit.SECONDS,
+ new LinkedBlockingQueue<Runnable>());
+
+ private ListenerRegistration<K> listenerRegistration;
+ protected final Class<T> clazz;
+ private final Class<K> eventClazz;
+
+ /**
+ * @param clazz - for which the data change event is received
+ */
+ public AsyncClusteredDataChangeListenerBase(Class<T> clazz, Class<K> eventClazz) {
+ this.clazz = Preconditions.checkNotNull(clazz, "Class can not be null!");
+ this.eventClazz = Preconditions.checkNotNull(eventClazz, "eventClazz can not be null!");
+ }
+
+ public void registerListener(final LogicalDatastoreType dsType, final DataBroker db) {
+ try {
+ TaskRetryLooper looper = new TaskRetryLooper(STARTUP_LOOP_TICK, STARTUP_LOOP_MAX_RETRIES);
+ listenerRegistration = looper.loopUntilNoException(new Callable<ListenerRegistration<K>>() {
+ @Override
+ public ListenerRegistration call() throws Exception {
+ return db.registerDataChangeListener(dsType, getWildCardPath(), getDataChangeListener(), getDataChangeScope());
+ }
+ });
+ } catch (final Exception e) {
+ LOG.warn("{}: Data Tree Change listener registration failed.", eventClazz.getName());
+ LOG.debug("{}: Data Tree Change listener registration failed: {}", eventClazz.getName(), e);
+ throw new IllegalStateException( eventClazz.getName() + "{}startup failed. System needs restart.", e);
+ }
+ }
+
+ @Override
+ public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
+ if (changeEvent == null) {
+ return;
+ }
+
+ DataChangeHandler dataChangeHandler = new DataChangeHandler(changeEvent);
+ dataChangeHandlerExecutor.execute(dataChangeHandler);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void createData(final Map<InstanceIdentifier<?>, DataObject> createdData) {
+ final Set<InstanceIdentifier<?>> keys = createdData.keySet() != null
+ ? createdData.keySet() : Collections.<InstanceIdentifier<?>>emptySet();
+ for (InstanceIdentifier<?> key : keys) {
+ if (clazz.equals(key.getTargetType())) {
+ InstanceIdentifier<T> createKeyIdent = key.firstIdentifierOf(clazz);
+ final Optional<DataObject> value = Optional.of(createdData.get(key));
+ if (value.isPresent()) {
+ this.add(createKeyIdent, (T)value.get());
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void updateData(final Map<InstanceIdentifier<?>, DataObject> updateData,
+ final Map<InstanceIdentifier<?>, DataObject> originalData) {
+
+ final Set<InstanceIdentifier<?>> keys = updateData.keySet() != null
+ ? updateData.keySet() : Collections.<InstanceIdentifier<?>>emptySet();
+ for (InstanceIdentifier<?> key : keys) {
+ if (clazz.equals(key.getTargetType())) {
+ InstanceIdentifier<T> updateKeyIdent = key.firstIdentifierOf(clazz);
+ final Optional<DataObject> value = Optional.of(updateData.get(key));
+ final Optional<DataObject> original = Optional.of(originalData.get(key));
+ if (value.isPresent() && original.isPresent()) {
+ this.update(updateKeyIdent, (T) original.get(), (T) value.get());
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void removeData(final Set<InstanceIdentifier<?>> removeData,
+ final Map<InstanceIdentifier<?>, DataObject> originalData) {
+
+ for (InstanceIdentifier<?> key : removeData) {
+ if (clazz.equals(key.getTargetType())) {
+ final InstanceIdentifier<T> ident = key.firstIdentifierOf(clazz);
+ final DataObject removeValue = originalData.get(key);
+ this.remove(ident, (T)removeValue);
+ }
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up ClusteredDataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("Interface Manager Closed");
+ }
+
+ protected abstract void remove(InstanceIdentifier<T> identifier, T del);
+
+ protected abstract void update(InstanceIdentifier<T> identifier, T original, T update);
+
+ protected abstract void add(InstanceIdentifier<T> identifier, T add);
+
+ protected abstract InstanceIdentifier<T> getWildCardPath();
+
+ protected abstract ClusteredDataChangeListener getDataChangeListener();
+
+ protected abstract AsyncDataBroker.DataChangeScope getDataChangeScope();
+
+ public class DataChangeHandler implements Runnable {
+ final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent;
+
+ public DataChangeHandler(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
+ this.changeEvent = changeEvent;
+ }
+
+ @Override
+ public void run() {
+ Preconditions.checkNotNull(changeEvent,"Async ChangeEvent can not be null!");
+
+ /* All DataObjects for create */
+ final Map<InstanceIdentifier<?>, DataObject> createdData = changeEvent.getCreatedData() != null
+ ? changeEvent.getCreatedData() : Collections.<InstanceIdentifier<?>, DataObject>emptyMap();
+ /* All DataObjects for remove */
+ final Set<InstanceIdentifier<?>> removeData = changeEvent.getRemovedPaths() != null
+ ? changeEvent.getRemovedPaths() : Collections.<InstanceIdentifier<?>>emptySet();
+ /* All DataObjects for updates */
+ final Map<InstanceIdentifier<?>, DataObject> updateData = changeEvent.getUpdatedData() != null
+ ? changeEvent.getUpdatedData() : Collections.<InstanceIdentifier<?>, DataObject>emptyMap();
+ /* All Original DataObjects */
+ final Map<InstanceIdentifier<?>, DataObject> originalData = changeEvent.getOriginalData() != null
+ ? changeEvent.getOriginalData() : Collections.<InstanceIdentifier<?>, DataObject>emptyMap();
+
+ createData(createdData);
+ updateData(updateData, originalData);
+ removeData(removeData, originalData);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.datastoreutils;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.*;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+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.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+public abstract class AsyncDataChangeListenerBase<T extends DataObject, K extends DataChangeListener> implements DataChangeListener, AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(AsyncDataChangeListenerBase.class);
+
+ private static final int DATATREE_CHANGE_HANDLER_THREAD_POOL_CORE_SIZE = 1;
+ private static final int DATATREE_CHANGE_HANDLER_THREAD_POOL_MAX_SIZE = 1;
+ private static final int DATATREE_CHANGE_HANDLER_THREAD_POOL_KEEP_ALIVE_TIME_SECS = 300;
+ private static final int STARTUP_LOOP_TICK = 500;
+ private static final int STARTUP_LOOP_MAX_RETRIES = 8;
+
+ private static ThreadPoolExecutor dataChangeHandlerExecutor = new ThreadPoolExecutor(
+ DATATREE_CHANGE_HANDLER_THREAD_POOL_CORE_SIZE,
+ DATATREE_CHANGE_HANDLER_THREAD_POOL_MAX_SIZE,
+ DATATREE_CHANGE_HANDLER_THREAD_POOL_KEEP_ALIVE_TIME_SECS,
+ TimeUnit.SECONDS,
+ new LinkedBlockingQueue<Runnable>());
+
+ private ListenerRegistration<K> listenerRegistration;
+ protected final Class<T> clazz;
+ private final Class<K> eventClazz;
+
+ /**
+ * @param clazz - for which the data change event is received
+ */
+ public AsyncDataChangeListenerBase(Class<T> clazz, Class<K> eventClazz) {
+ this.clazz = Preconditions.checkNotNull(clazz, "Class can not be null!");
+ this.eventClazz = Preconditions.checkNotNull(eventClazz, "eventClazz can not be null!");
+ }
+
+ public void registerListener(final LogicalDatastoreType dsType, final DataBroker db) {
+ try {
+ TaskRetryLooper looper = new TaskRetryLooper(STARTUP_LOOP_TICK, STARTUP_LOOP_MAX_RETRIES);
+ listenerRegistration = looper.loopUntilNoException(new Callable<ListenerRegistration<K>>() {
+ @Override
+ public ListenerRegistration call() throws Exception {
+ return db.registerDataChangeListener(dsType, getWildCardPath(), getDataChangeListener(), getDataChangeScope());
+ }
+ });
+ } catch (final Exception e) {
+ LOG.warn("{}: Data Tree Change listener registration failed.", eventClazz.getName());
+ LOG.debug("{}: Data Tree Change listener registration failed: {}", eventClazz.getName(), e);
+ throw new IllegalStateException( eventClazz.getName() + "{}startup failed. System needs restart.", e);
+ }
+ }
+
+ @Override
+ public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
+ if (changeEvent == null) {
+ return;
+ }
+
+ DataChangeHandler dataChangeHandler = new DataChangeHandler(changeEvent);
+ dataChangeHandlerExecutor.execute(dataChangeHandler);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void createData(final Map<InstanceIdentifier<?>, DataObject> createdData) {
+ final Set<InstanceIdentifier<?>> keys = createdData.keySet() != null
+ ? createdData.keySet() : Collections.<InstanceIdentifier<?>>emptySet();
+ for (InstanceIdentifier<?> key : keys) {
+ if (clazz.equals(key.getTargetType())) {
+ InstanceIdentifier<T> createKeyIdent = key.firstIdentifierOf(clazz);
+ final Optional<DataObject> value = Optional.of(createdData.get(key));
+ if (value.isPresent()) {
+ this.add(createKeyIdent, (T)value.get());
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void updateData(final Map<InstanceIdentifier<?>, DataObject> updateData,
+ final Map<InstanceIdentifier<?>, DataObject> originalData) {
+
+ final Set<InstanceIdentifier<?>> keys = updateData.keySet() != null
+ ? updateData.keySet() : Collections.<InstanceIdentifier<?>>emptySet();
+ for (InstanceIdentifier<?> key : keys) {
+ if (clazz.equals(key.getTargetType())) {
+ InstanceIdentifier<T> updateKeyIdent = key.firstIdentifierOf(clazz);
+ final Optional<DataObject> value = Optional.of(updateData.get(key));
+ final Optional<DataObject> original = Optional.of(originalData.get(key));
+ if (value.isPresent() && original.isPresent()) {
+ this.update(updateKeyIdent, (T) original.get(), (T) value.get());
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void removeData(final Set<InstanceIdentifier<?>> removeData,
+ final Map<InstanceIdentifier<?>, DataObject> originalData) {
+
+ for (InstanceIdentifier<?> key : removeData) {
+ if (clazz.equals(key.getTargetType())) {
+ final InstanceIdentifier<T> ident = key.firstIdentifierOf(clazz);
+ final DataObject removeValue = originalData.get(key);
+ this.remove(ident, (T)removeValue);
+ }
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("Interface Manager Closed");
+ }
+
+ protected abstract void remove(InstanceIdentifier<T> identifier, T del);
+
+ protected abstract void update(InstanceIdentifier<T> identifier, T original, T update);
+
+ protected abstract void add(InstanceIdentifier<T> identifier, T add);
+
+ protected abstract InstanceIdentifier<T> getWildCardPath();
+
+ protected abstract DataChangeListener getDataChangeListener();
+
+ protected abstract AsyncDataBroker.DataChangeScope getDataChangeScope();
+
+ public class DataChangeHandler implements Runnable {
+ final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent;
+
+ public DataChangeHandler(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
+ this.changeEvent = changeEvent;
+ }
+
+ @Override
+ public void run() {
+ Preconditions.checkNotNull(changeEvent,"Async ChangeEvent can not be null!");
+
+ /* All DataObjects for create */
+ final Map<InstanceIdentifier<?>, DataObject> createdData = changeEvent.getCreatedData() != null
+ ? changeEvent.getCreatedData() : Collections.<InstanceIdentifier<?>, DataObject>emptyMap();
+ /* All DataObjects for remove */
+ final Set<InstanceIdentifier<?>> removeData = changeEvent.getRemovedPaths() != null
+ ? changeEvent.getRemovedPaths() : Collections.<InstanceIdentifier<?>>emptySet();
+ /* All DataObjects for updates */
+ final Map<InstanceIdentifier<?>, DataObject> updateData = changeEvent.getUpdatedData() != null
+ ? changeEvent.getUpdatedData() : Collections.<InstanceIdentifier<?>, DataObject>emptyMap();
+ /* All Original DataObjects */
+ final Map<InstanceIdentifier<?>, DataObject> originalData = changeEvent.getOriginalData() != null
+ ? changeEvent.getOriginalData() : Collections.<InstanceIdentifier<?>, DataObject>emptyMap();
+
+ createData(createdData);
+ updateData(updateData, originalData);
+ removeData(removeData, originalData);
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.datastoreutils;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.*;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+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.util.Collection;
+import java.util.concurrent.Callable;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+public abstract class AsyncDataTreeChangeListenerBase<T extends DataObject, K extends DataTreeChangeListener> implements DataTreeChangeListener<T>, AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(AsyncDataTreeChangeListenerBase.class);
+
+ private static final int DATATREE_CHANGE_HANDLER_THREAD_POOL_CORE_SIZE = 1;
+ private static final int DATATREE_CHANGE_HANDLER_THREAD_POOL_MAX_SIZE = 1;
+ private static final int DATATREE_CHANGE_HANDLER_THREAD_POOL_KEEP_ALIVE_TIME_SECS = 300;
+ private static final int STARTUP_LOOP_TICK = 500;
+ private static final int STARTUP_LOOP_MAX_RETRIES = 8;
+
+ private ListenerRegistration<K> listenerRegistration;
+
+ private static ThreadPoolExecutor dataTreeChangeHandlerExecutor = new ThreadPoolExecutor(
+ DATATREE_CHANGE_HANDLER_THREAD_POOL_CORE_SIZE,
+ DATATREE_CHANGE_HANDLER_THREAD_POOL_MAX_SIZE,
+ DATATREE_CHANGE_HANDLER_THREAD_POOL_KEEP_ALIVE_TIME_SECS,
+ TimeUnit.SECONDS,
+ new LinkedBlockingQueue<Runnable>());
+
+ protected final Class<T> clazz;
+ private final Class<K> eventClazz;
+
+ public AsyncDataTreeChangeListenerBase(Class<T> clazz, Class<K> eventClazz) {
+ this.clazz = Preconditions.checkNotNull(clazz, "Class can not be null!");
+ this.eventClazz = Preconditions.checkNotNull(eventClazz, "eventClazz can not be null!");
+ }
+
+ @Override
+ public void onDataTreeChanged(Collection<DataTreeModification<T>> changes) {
+ if (changes == null || changes.isEmpty()) {
+ return;
+ }
+
+ DataTreeChangeHandler dataTreeChangeHandler = new DataTreeChangeHandler(changes);
+ dataTreeChangeHandlerExecutor.execute(dataTreeChangeHandler);
+ }
+
+ public void registerListener(LogicalDatastoreType dsType, final DataBroker db) {
+ final DataTreeIdentifier<T> treeId = new DataTreeIdentifier<>(dsType, getWildCardPath());
+ try {
+ TaskRetryLooper looper = new TaskRetryLooper(STARTUP_LOOP_TICK, STARTUP_LOOP_MAX_RETRIES);
+ listenerRegistration = looper.loopUntilNoException(new Callable<ListenerRegistration<K>>() {
+ @Override
+ public ListenerRegistration<K> call() throws Exception {
+ return db.registerDataTreeChangeListener(treeId, getDataTreeChangeListener());
+ }
+ });
+ } catch (final Exception e) {
+ LOG.warn("{}: Data Tree Change listener registration failed.", eventClazz.getName());
+ LOG.debug("{}: Data Tree Change listener registration failed: {}", eventClazz.getName(), e);
+ throw new IllegalStateException( eventClazz.getName() + "{}startup failed. System needs restart.", e);
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataTreeChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ }
+
+ protected abstract InstanceIdentifier<T> getWildCardPath();
+ protected abstract void remove(InstanceIdentifier<T> key, T dataObjectModification);
+ protected abstract void update(InstanceIdentifier<T> key, T dataObjectModificationBefore, T dataObjectModificationAfter);
+ protected abstract void add(InstanceIdentifier<T> key, T dataObjectModification);
+ protected abstract K getDataTreeChangeListener();
+
+ public class DataTreeChangeHandler implements Runnable {
+ Collection<DataTreeModification<T>> changes;
+
+ public DataTreeChangeHandler(Collection<DataTreeModification<T>> changes) {
+ this.changes = changes;
+ }
+
+
+
+ @Override
+ public void run() {
+ for (DataTreeModification<T> change : changes) {
+ final InstanceIdentifier<T> key = change.getRootPath().getRootIdentifier();
+ final DataObjectModification<T> mod = change.getRootNode();
+
+ switch (mod.getModificationType()) {
+ case DELETE:
+ remove(key, mod.getDataBefore());
+ break;
+ case SUBTREE_MODIFIED:
+ update(key, mod.getDataBefore(), mod.getDataAfter());
+ break;
+ case WRITE:
+ if (mod.getDataBefore() == null) {
+ add(key, mod.getDataAfter());
+ } else {
+ update(key, mod.getDataBefore(), mod.getDataAfter());
+ }
+ break;
+ default:
+ // FIXME: May be not a good idea to throw.
+ throw new IllegalArgumentException("Unhandled modification type " + mod.getModificationType());
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.datastoreutils;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.TimeUnit;
+
+public class DataStoreJobCoordinator {
+ private static final Logger LOG = LoggerFactory.getLogger(DataStoreJobCoordinator.class);
+
+ private static final int THREADPOOL_SIZE = Runtime.getRuntime().availableProcessors();
+
+ private ForkJoinPool fjPool;
+ private Map<Integer,Map<String, JobQueue>> jobQueueMap = new ConcurrentHashMap<>();
+
+ private static DataStoreJobCoordinator instance;
+
+ static {
+ instance = new DataStoreJobCoordinator();
+ }
+
+ public static DataStoreJobCoordinator getInstance() {
+ return instance;
+ }
+
+ /**
+ *
+ */
+ private DataStoreJobCoordinator() {
+ fjPool = new ForkJoinPool();
+
+ for (int i = 0; i < THREADPOOL_SIZE; i++) {
+ Map<String, JobQueue> jobEntriesMap = new ConcurrentHashMap<String, JobQueue>();
+ jobQueueMap.put(i, jobEntriesMap);
+ }
+
+ new Thread(new JobQueueHandler()).start();
+ }
+
+ public void enqueueJob(String key,
+ Callable<List<ListenableFuture<Void>>> mainWorker) {
+ enqueueJob(key, mainWorker, null, 0);
+ }
+
+ public void enqueueJob(String key,
+ Callable<List<ListenableFuture<Void>>> mainWorker,
+ RollbackCallable rollbackWorker) {
+ enqueueJob(key, mainWorker, rollbackWorker, 0);
+ }
+
+ public void enqueueJob(String key,
+ Callable<List<ListenableFuture<Void>>> mainWorker,
+ int maxRetries) {
+ enqueueJob(key, mainWorker, null, maxRetries);
+ }
+
+ /**
+ *
+ * @param key
+ * @param mainWorker
+ * @param rollbackWorker
+ * @param maxRetries
+ *
+ * This is used by the external applications to enqueue a Job with an appropriate key.
+ * A JobEntry is created and queued appropriately.
+ */
+
+ public void enqueueJob(String key,
+ Callable<List<ListenableFuture<Void>>> mainWorker,
+ RollbackCallable rollbackWorker,
+ int maxRetries) {
+ JobEntry jobEntry = new JobEntry(key, mainWorker, rollbackWorker, maxRetries);
+ Integer hashKey = getHashKey(key);
+ LOG.debug("Obtained Hashkey: {}, for jobkey: {}", hashKey, key);
+
+ Map<String, JobQueue> jobEntriesMap = jobQueueMap.get(hashKey);
+ synchronized (jobEntriesMap) {
+ JobQueue jobQueue = jobEntriesMap.get(key);
+ if (jobQueue == null) {
+ jobQueue = new JobQueue();
+ }
+ jobQueue.addEntry(jobEntry);
+ jobEntriesMap.put(key, jobQueue);
+ }
+
+ jobQueueMap.put(hashKey, jobEntriesMap); // Is this really needed ?
+ }
+
+ /**
+ * clearJob is used to cleanup the submitted job from the jobqueue.
+ **/
+ private void clearJob(JobEntry jobEntry) {
+ Map<String, JobQueue> jobEntriesMap = jobQueueMap.get(getHashKey(jobEntry.getKey()));
+ synchronized (jobEntriesMap) {
+ JobQueue jobQueue = jobEntriesMap.get(jobEntry.getKey());
+ jobQueue.setExecutingEntry(null);
+ if (jobQueue.getWaitingEntries().isEmpty()) {
+ jobEntriesMap.remove(jobEntry.getKey());
+ }
+ }
+ }
+
+ /**
+ *
+ * @param key
+ * @return generated hashkey
+ *
+ * Used to generate the hashkey in to the jobQueueMap.
+ */
+ private Integer getHashKey(String key) {
+ int code = key.hashCode();
+ return (code % THREADPOOL_SIZE + THREADPOOL_SIZE) % THREADPOOL_SIZE;
+ }
+
+ /**
+ * JobCallback class is used as a future callback for
+ * main and rollback workers to handle success and failure.
+ */
+ private class JobCallback implements FutureCallback<List<Void>> {
+ private JobEntry jobEntry;
+
+ public JobCallback(JobEntry jobEntry) {
+ this.jobEntry = jobEntry;
+ }
+
+ /**
+ * @param voids
+ * This implies that all the future instances have returned success. -- TODO: Confirm this
+ */
+ @Override
+ public void onSuccess(List<Void> voids) {
+ clearJob(jobEntry);
+ }
+
+ /**
+ *
+ * @param throwable
+ * This method is used to handle failure callbacks.
+ * If more retry needed, the retrycount is decremented and mainworker is executed again.
+ * After retries completed, rollbackworker is executed.
+ * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
+ */
+
+ @Override
+ public void onFailure(Throwable throwable) {
+ LOG.warn("Job: {} failed with exception: {}", jobEntry, throwable.getStackTrace());
+ if (jobEntry.getMainWorker() == null) {
+ LOG.error("Job: {} failed with Double-Fault. Bailing Out.", jobEntry);
+ clearJob(jobEntry);
+ return;
+ }
+
+ if (jobEntry.decrementRetryCountAndGet() > 0) {
+ MainTask worker = new MainTask(jobEntry);
+ fjPool.execute(worker);
+ return;
+ }
+
+ if (jobEntry.getRollbackWorker() != null) {
+ jobEntry.setMainWorker(null);
+ RollbackTask rollbackTask = new RollbackTask(jobEntry);
+ fjPool.execute(rollbackTask);
+ return;
+ }
+
+ clearJob(jobEntry);
+ }
+ }
+
+ /**
+ * RollbackTask is used to execute the RollbackCallable provided by the application
+ * in the eventuality of a failure.
+ */
+
+ private class RollbackTask implements Runnable {
+ private JobEntry jobEntry;
+
+ public RollbackTask(JobEntry jobEntry) {
+ this.jobEntry = jobEntry;
+ }
+
+ @Override
+ public void run() {
+ RollbackCallable callable = jobEntry.getRollbackWorker();
+ callable.setFutures(jobEntry.getFutures());
+ List<ListenableFuture<Void>> futures = null;
+
+ try {
+ futures = callable.call();
+ } catch (Exception e){
+ LOG.error("Exception when executing jobEntry: {}, exception: {}", jobEntry, e.getStackTrace());
+ e.printStackTrace();
+ }
+
+ if (futures == null || futures.isEmpty()) {
+ clearJob(jobEntry);
+ return;
+ }
+
+ ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
+ Futures.addCallback(listenableFuture, new JobCallback(jobEntry));
+ jobEntry.setFutures(futures);
+ }
+ }
+
+ /**
+ * MainTask is used to execute the MainWorker callable.
+ */
+
+ private class MainTask implements Runnable {
+ private JobEntry jobEntry;
+
+ public MainTask(JobEntry jobEntry) {
+ this.jobEntry = jobEntry;
+ }
+
+ @Override
+ public void run() {
+ List<ListenableFuture<Void>> futures = null;
+ try {
+ futures = jobEntry.getMainWorker().call();
+ } catch (Exception e){
+ LOG.error("Exception when executing jobEntry: {}, exception: {}", jobEntry, e.getStackTrace());
+ e.printStackTrace();
+ }
+
+ if (futures == null || futures.isEmpty()) {
+ clearJob(jobEntry);
+ return;
+ }
+
+ ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
+ Futures.addCallback(listenableFuture, new JobCallback(jobEntry));
+ jobEntry.setFutures(futures);
+ }
+ }
+
+ private class JobQueueHandler implements Runnable {
+ @Override
+ public void run() {
+ LOG.debug("Starting JobQueue Handler Thread.");
+ while (true) {
+ try {
+ boolean jobAddedToPool = false;
+ for (int i = 0; i < THREADPOOL_SIZE; i++) {
+ Map<String, JobQueue> jobEntriesMap = jobQueueMap.get(i);
+ if (jobEntriesMap.isEmpty()) {
+ continue;
+ }
+
+ synchronized (jobEntriesMap) {
+ Iterator it = jobEntriesMap.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<String, JobQueue> entry = (Map.Entry)it.next();
+ if (entry.getValue().getExecutingEntry() != null) {
+ continue;
+ }
+ JobEntry jobEntry = entry.getValue().getWaitingEntries().poll();
+ if (jobEntry != null) {
+ entry.getValue().setExecutingEntry(jobEntry);
+ MainTask worker = new MainTask(jobEntry);
+ fjPool.execute(worker);
+ jobAddedToPool = true;
+ } else {
+ it.remove();
+ }
+ }
+ }
+ }
+
+ if (!jobAddedToPool) {
+ TimeUnit.SECONDS.sleep(1);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.datastoreutils;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * JobEntry is the entity built per job submitted by the application and
+ * enqueued to the book-keeping data structure.
+ */
+public class JobEntry {
+ final private String key;
+ private Callable<List<ListenableFuture<Void>>> mainWorker;
+ final private RollbackCallable rollbackWorker;
+ private AtomicInteger retryCount;
+ private List<ListenableFuture<Void>> futures;
+
+ public JobEntry(String key,
+ Callable<List<ListenableFuture<Void>>> mainWorker,
+ RollbackCallable rollbackWorker,
+ int maxRetries) {
+ this.key = key;
+ this.mainWorker = mainWorker;
+ this.rollbackWorker = rollbackWorker;
+ retryCount = new AtomicInteger(maxRetries);
+ }
+
+ /**
+ *
+ * @return
+ *
+ * The key provided by the application that segregates the
+ * callables that can be run parallely.
+ * NOTE: Currently, this is a string. Can be converted to Object where
+ * Object implementation should provide the hashcode and equals methods.
+ */
+ public String getKey() {
+ return key;
+ }
+
+ public Callable<List<ListenableFuture<Void>>> getMainWorker() {
+ return mainWorker;
+ }
+
+ public void setMainWorker(Callable<List<ListenableFuture<Void>>> mainWorker) {
+ this.mainWorker = mainWorker;
+ }
+
+ public RollbackCallable getRollbackWorker() {
+ return rollbackWorker;
+ }
+
+ public int decrementRetryCountAndGet() {
+ return retryCount.decrementAndGet();
+ }
+
+ public List<ListenableFuture<Void>> getFutures() {
+ return futures;
+ }
+
+ public void setFutures(List<ListenableFuture<Void>> futures) {
+ this.futures = futures;
+ }
+
+ @Override
+ public String toString() {
+ return "JobEntry{" +
+ "key='" + key + '\'' +
+ ", mainWorker=" + mainWorker +
+ ", rollbackWorker=" + rollbackWorker +
+ ", retryCount=" + retryCount +
+ ", futures=" + futures +
+ '}';
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.datastoreutils;
+
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+public class JobQueue {
+ private ConcurrentLinkedQueue<JobEntry> waitingEntries;
+ private JobEntry executingEntry;
+
+ public JobQueue() {
+ waitingEntries = new ConcurrentLinkedQueue<JobEntry>();
+ }
+
+ public void addEntry(JobEntry entry) {
+ waitingEntries.add(entry); // FIXME - Try/Catch.
+ }
+
+ public ConcurrentLinkedQueue<JobEntry> getWaitingEntries() {
+ return waitingEntries;
+ }
+
+ public JobEntry getExecutingEntry() {
+ return executingEntry;
+ }
+
+ public void setExecutingEntry(JobEntry executingEntry) {
+ this.executingEntry = executingEntry;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.datastoreutils;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+
+public abstract class RollbackCallable implements Callable<List<ListenableFuture<Void>>> {
+
+ private List<ListenableFuture<Void>> futures;
+
+ public RollbackCallable() {
+ }
+
+ public List<ListenableFuture<Void>> getFutures() {
+ return futures;
+ }
+
+ public void setFutures(List<ListenableFuture<Void>> futures) {
+ this.futures = futures;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.datastoreutils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.Callable;
+
+public class TaskRetryLooper {
+ private static final Logger LOG = LoggerFactory.getLogger(TaskRetryLooper.class);
+
+ private final long tick;
+ private final int maxRetries;
+
+ /**
+ * @param tick sleep between steps in miliseconds
+ * @param maxRetries retries limit
+ */
+ public TaskRetryLooper(long tick, int maxRetries) {
+ this.tick = tick;
+ this.maxRetries = maxRetries;
+ }
+
+ public <T> T loopUntilNoException(Callable<T> task) throws Exception {
+ T output = null;
+
+ Exception taskException = null;
+ for (int i = 0; i < maxRetries; i++) {
+ taskException = null;
+ try {
+ output = task.call();
+ break;
+ } catch (Exception exception) {
+ LOG.debug("looper step failed: {}", exception.getMessage());
+ taskException = exception;
+ }
+
+ try {
+ Thread.sleep(tick);
+ } catch (InterruptedException e) {
+ LOG.debug("interrupted: {}", e.getMessage(), e);
+ }
+ }
+
+ if (taskException != null) {
+ throw taskException;
+ }
+
+ LOG.debug("looper step succeeded: {}", output);
+ return output;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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 com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * AbstractDataChangeListener implemented basic {@link DataChangeListener} processing for
+ * MDSAL Data Objects.
+ */
+public abstract class AbstractDataChangeListener<T extends DataObject> implements DataChangeListener {
+
+ protected final Class<T> clazz;
+
+ /**
+ * @param clazz - for which the data change event is received
+ */
+ public AbstractDataChangeListener(Class<T> clazz) {
+ this.clazz = Preconditions.checkNotNull(clazz, "Class can not be null!");
+ }
+
+ @Override
+ public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
+ Preconditions.checkNotNull(changeEvent,"Async ChangeEvent can not be null!");
+
+ /* All DataObjects for create */
+ final Map<InstanceIdentifier<?>, DataObject> createdData = changeEvent.getCreatedData() != null
+ ? changeEvent.getCreatedData() : Collections.<InstanceIdentifier<?>, DataObject>emptyMap();
+ /* All DataObjects for remove */
+ final Set<InstanceIdentifier<?>> removeData = changeEvent.getRemovedPaths() != null
+ ? changeEvent.getRemovedPaths() : Collections.<InstanceIdentifier<?>>emptySet();
+ /* All DataObjects for updates */
+ final Map<InstanceIdentifier<?>, DataObject> updateData = changeEvent.getUpdatedData() != null
+ ? changeEvent.getUpdatedData() : Collections.<InstanceIdentifier<?>, DataObject>emptyMap();
+ /* All Original DataObjects */
+ final Map<InstanceIdentifier<?>, DataObject> originalData = changeEvent.getOriginalData() != null
+ ? changeEvent.getOriginalData() : Collections.<InstanceIdentifier<?>, DataObject>emptyMap();
+
+ this.createData(createdData);
+ this.updateData(updateData, originalData);
+ this.removeData(removeData, originalData);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void createData(final Map<InstanceIdentifier<?>, DataObject> createdData) {
+ final Set<InstanceIdentifier<?>> keys = createdData.keySet() != null
+ ? createdData.keySet() : Collections.<InstanceIdentifier<?>>emptySet();
+ for (InstanceIdentifier<?> key : keys) {
+ if (clazz.equals(key.getTargetType())) {
+ InstanceIdentifier<T> createKeyIdent = key.firstIdentifierOf(clazz);
+ final Optional<DataObject> value = Optional.of(createdData.get(key));
+ if (value.isPresent()) {
+ this.add(createKeyIdent, (T)value.get());
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void updateData(final Map<InstanceIdentifier<?>, DataObject> updateData,
+ final Map<InstanceIdentifier<?>, DataObject> originalData) {
+
+ final Set<InstanceIdentifier<?>> keys = updateData.keySet() != null
+ ? updateData.keySet() : Collections.<InstanceIdentifier<?>>emptySet();
+ for (InstanceIdentifier<?> key : keys) {
+ if (clazz.equals(key.getTargetType())) {
+ InstanceIdentifier<T> updateKeyIdent = key.firstIdentifierOf(clazz);
+ final Optional<DataObject> value = Optional.of(updateData.get(key));
+ final Optional<DataObject> original = Optional.of(originalData.get(key));
+ if (value.isPresent() && original.isPresent()) {
+ this.update(updateKeyIdent, (T)original.get(), (T)value.get());
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void removeData(final Set<InstanceIdentifier<?>> removeData,
+ final Map<InstanceIdentifier<?>, DataObject> originalData) {
+
+ for (InstanceIdentifier<?> key : removeData) {
+ if (clazz.equals(key.getTargetType())) {
+ final InstanceIdentifier<T> ident = key.firstIdentifierOf(clazz);
+ final DataObject removeValue = originalData.get(key);
+ this.remove(ident, (T)removeValue);
+ }
+ }
+ }
+
+ protected abstract void remove(InstanceIdentifier<T> identifier, T del);
+
+ protected abstract void update(InstanceIdentifier<T> identifier, T original, T update);
+
+ protected abstract void add(InstanceIdentifier<T> identifier, T add);
+
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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 class AbstractSwitchEntity {
+ private static final long serialVersionUID = 1L;
+
+ private BigInteger m_dpnId;
+
+
+ public AbstractSwitchEntity(BigInteger dpnId) {
+ m_dpnId = dpnId;
+ }
+
+ @Override
+ public String toString() {
+ return "AbstractSwitchEntity [m_lDpnId=" + m_dpnId + " ]";
+ }
+
+
+ public BigInteger getDpnId() {
+ return m_dpnId;
+ }
+
+ public void setDpnId(BigInteger dpnId) {
+ m_dpnId = dpnId;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.io.Serializable;
+import java.math.BigInteger;
+import java.util.Arrays;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+
+public class ActionInfo implements Serializable{
+
+ private static final long serialVersionUID = 1L;
+ private final ActionType m_actionType;
+ private String[] m_asActionValues = null;
+ private BigInteger [] m_aBigIntValues;
+ private int m_actionKey = 0;
+
+ public ActionInfo(ActionInfo action) {
+ super();
+ m_actionType = action.m_actionType;
+ m_actionKey = action.m_actionKey;
+ m_asActionValues = Arrays.copyOf(action.m_asActionValues, action.m_asActionValues.length);
+ }
+
+ public ActionInfo(ActionType actionType, String[] asActionValues) {
+ m_actionType = actionType;
+ m_actionKey = 0;
+ m_asActionValues = asActionValues;
+ }
+
+ public ActionInfo(ActionType actionType, String[] asActionValues, int actionKey) {
+ m_actionType = actionType;
+ m_actionKey = actionKey;
+ m_asActionValues = asActionValues;
+ }
+
+ public ActionInfo(ActionType actionType, BigInteger[] aBigIntValues) {
+ m_actionType = actionType;
+ m_actionKey = 0;
+ m_aBigIntValues = aBigIntValues;
+ }
+
+ public ActionInfo(ActionType actionType, BigInteger[] aBigIntValues, int actionKey) {
+ m_actionType = actionType;
+ m_actionKey = actionKey;
+ m_aBigIntValues = aBigIntValues;
+ }
+
+ public void setActionKey(int key) {
+ m_actionKey = key;
+ }
+
+ public int getActionKey() {
+ return m_actionKey;
+ }
+
+ public Action buildAction() {
+ return m_actionType.buildAction(this);
+ }
+
+ public ActionType getActionType() {
+ return m_actionType;
+ }
+
+ public String[] getActionValues() {
+ return m_asActionValues;
+ }
+
+ public BigInteger[] getBigActionValues() {
+ return m_aBigIntValues;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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 java.net.InetAddress;
+
+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.OutputActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopMplsActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopPbbActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushMplsActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushPbbActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PushVlanActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.group.action._case.GroupActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.output.action._case.OutputActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.mpls.action._case.PopMplsActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.pbb.action._case.PopPbbActionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanActionBuilder;
+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.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.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.ProtocolMatchFieldsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TunnelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
+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.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
+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.TcpMatchBuilder;
+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.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.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.nx.action.resubmit.grouping.NxResubmitBuilder;
+
+public enum ActionType {
+ group {
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ long groupId = Long.parseLong(actionInfo.getActionValues()[0]);
+
+ return new ActionBuilder().setAction(
+ new GroupActionCaseBuilder().setGroupAction(
+ new GroupActionBuilder().setGroupId(groupId).build()).build())
+ .setKey(new ActionKey(actionInfo.getActionKey())).build();
+ }
+ },
+
+ output {
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ String[] actionValues = actionInfo.getActionValues();
+ String port = actionValues[0];
+ int maxLength = 0;
+
+ if (actionValues.length == 2) {
+ maxLength = Integer.valueOf(actionValues[1]);
+ }
+
+ return new ActionBuilder().setAction(
+ new OutputActionCaseBuilder().setOutputAction(
+ new OutputActionBuilder().setMaxLength(Integer.valueOf(maxLength))
+ .setOutputNodeConnector(new Uri(port)).build()).build())
+ .setKey(new ActionKey(actionInfo.getActionKey())).build();
+ }
+ },
+
+ pop_mpls {
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ return new ActionBuilder().setAction(
+ new PopMplsActionCaseBuilder().setPopMplsAction(
+ new PopMplsActionBuilder().setEthernetType(
+ Integer.valueOf(NwConstants.ETHTYPE_IPV4)).build()).build())
+
+ .setKey(new ActionKey(actionInfo.getActionKey())).build();
+ }
+ },
+
+ pop_pbb {
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ return new ActionBuilder()
+ .setAction(new PopPbbActionCaseBuilder().setPopPbbAction(new PopPbbActionBuilder().build()).build())
+ .setKey(new ActionKey(actionInfo.getActionKey())).build();
+ }
+ },
+
+ pop_vlan {
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ return new ActionBuilder().setAction(
+ new PopVlanActionCaseBuilder().setPopVlanAction(new PopVlanActionBuilder().build()).build())
+ .setKey(new ActionKey(actionInfo.getActionKey())).build();
+ }
+ },
+
+ push_mpls {
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ return new ActionBuilder().setAction(new PushMplsActionCaseBuilder().setPushMplsAction(
+ new PushMplsActionBuilder().setEthernetType(
+ Integer.valueOf(NwConstants.ETHTYPE_MPLS_UC)).build()).build())
+ .setKey(new ActionKey(actionInfo.getActionKey())).build();
+ }
+ },
+
+ push_pbb {
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ return new ActionBuilder().setAction(
+ new PushPbbActionCaseBuilder().setPushPbbAction(
+ new PushPbbActionBuilder()
+ .setEthernetType(Integer.valueOf(NwConstants.ETHTYPE_PBB)).build()).build())
+ .setKey(new ActionKey(actionInfo.getActionKey())).build();
+ }
+ },
+
+ push_vlan {
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ return new ActionBuilder().setAction(
+ new PushVlanActionCaseBuilder().setPushVlanAction(
+ new PushVlanActionBuilder().setEthernetType(
+ Integer.valueOf(NwConstants.ETHTYPE_802_1Q)).build()).build())
+ .setKey(new ActionKey(actionInfo.getActionKey())).build();
+ }
+ },
+
+ set_field_mpls_label {
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ String[] actionValues = actionInfo.getActionValues();
+ long label = Long.valueOf(actionValues[0]);
+
+ return new ActionBuilder().setAction(
+ new SetFieldCaseBuilder().setSetField(new SetFieldBuilder().setProtocolMatchFields(
+ new ProtocolMatchFieldsBuilder().setMplsLabel(label).build()).build())
+ .build()).setKey(new ActionKey(actionInfo.getActionKey())).build();
+ }
+ },
+
+ set_field_pbb_isid {
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ String[] actionValues = actionInfo.getActionValues();
+ long label = Long.valueOf(actionValues[0]);
+
+ return new ActionBuilder().setAction(
+ new SetFieldCaseBuilder().setSetField(
+ new SetFieldBuilder().setProtocolMatchFields(
+ new ProtocolMatchFieldsBuilder().setPbb(
+ new PbbBuilder().setPbbIsid(label).build()).build()).build())
+ .build()).setKey(new ActionKey(actionInfo.getActionKey())).build();
+ }
+ },
+
+ set_field_vlan_vid {
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ String[] actionValues = actionInfo.getActionValues();
+ int vlanId = Integer.valueOf(actionValues[0]);
+
+ return new ActionBuilder().setAction(
+ new SetFieldCaseBuilder().setSetField(
+ new SetFieldBuilder().setVlanMatch(
+ new VlanMatchBuilder().setVlanId(
+ new VlanIdBuilder().setVlanId(new VlanId(vlanId))
+ .setVlanIdPresent(true).build()).build()).build()).build())
+ .setKey(new ActionKey(actionInfo.getActionKey())).build();
+ }
+ },
+
+ set_field_tunnel_id {
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ BigInteger [] actionValues = actionInfo.getBigActionValues();
+ if (actionValues.length == 2) {
+ return new ActionBuilder().setAction(
+ new SetFieldCaseBuilder().setSetField(
+ new SetFieldBuilder()
+ .setTunnel(new TunnelBuilder().setTunnelId(actionValues[0])
+ .setTunnelMask(actionValues[1]).build()).build())
+ .build())
+ .setKey(new ActionKey(actionInfo.getActionKey())).build();
+ } else {
+ return new ActionBuilder().setAction(
+ new SetFieldCaseBuilder().setSetField(
+ new SetFieldBuilder()
+ .setTunnel(new TunnelBuilder().setTunnelId(actionValues[0])
+ .build()).build())
+ .build())
+ .setKey(new ActionKey(actionInfo.getActionKey())).build();
+ }
+
+ }
+
+ },
+
+ set_field_eth_dest {
+
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ String[] actionValues = actionInfo.getActionValues();
+ MacAddress mac = new MacAddress(actionValues[0]);
+
+ return new ActionBuilder().setAction(
+ new SetFieldCaseBuilder().setSetField(
+ new SetFieldBuilder().setEthernetMatch(
+ new EthernetMatchBuilder().setEthernetDestination(
+ new EthernetDestinationBuilder().setAddress(mac).build()).build())
+ .build()).build()).setKey(new ActionKey(actionInfo.getActionKey())).build();
+
+ }
+
+ },
+
+ set_udp_protocol {
+
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ return new ActionBuilder().setAction(
+ new SetFieldCaseBuilder().setSetField(
+ new SetFieldBuilder().setIpMatch(
+ new IpMatchBuilder().setIpProtocol((short) 17).build()).
+ build()).build()).setKey(new ActionKey(actionInfo.getActionKey())).build();
+
+ }
+
+ },
+ punt_to_controller {
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ ActionBuilder ab = new ActionBuilder();
+ OutputActionBuilder output = new OutputActionBuilder();
+ output.setMaxLength(0xffff);
+ Uri value = new Uri(OutputPortValues.CONTROLLER.toString());
+ output.setOutputNodeConnector(value);
+ ab.setAction(new OutputActionCaseBuilder().setOutputAction(output.build()).build());
+ ab.setKey(new ActionKey(actionInfo.getActionKey()));
+ return ab.build();
+ }
+
+ },
+ set_udp_destination_port {
+
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ String[] actionValues = actionInfo.getActionValues();
+ Integer portNumber = new Integer(actionValues[0]);
+
+ return new ActionBuilder().setAction(
+ new SetFieldCaseBuilder().setSetField(
+ new SetFieldBuilder().setLayer4Match(
+ new UdpMatchBuilder().setUdpDestinationPort(
+ new PortNumber(portNumber)).build())
+ .build()).build()).setKey(new ActionKey(actionInfo.getActionKey())).build();
+
+ }
+
+ },
+ set_udp_source_port {
+
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ String[] actionValues = actionInfo.getActionValues();
+ Integer portNumber = new Integer(actionValues[0]);
+
+ return new ActionBuilder().setAction(
+ new SetFieldCaseBuilder().setSetField(
+ new SetFieldBuilder().setLayer4Match(
+ new UdpMatchBuilder().setUdpSourcePort(
+ new PortNumber(portNumber)).build())
+ .build()).build()).setKey(new ActionKey(actionInfo.getActionKey())).build();
+
+ }
+
+ },
+ set_tcp_destination_port {
+
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ String[] actionValues = actionInfo.getActionValues();
+ Integer portNumber = new Integer(actionValues[0]);
+
+ return new ActionBuilder().setAction(
+ new SetFieldCaseBuilder().setSetField(
+ new SetFieldBuilder().setLayer4Match(
+ new TcpMatchBuilder().setTcpDestinationPort(
+ new PortNumber(portNumber)).build())
+ .build()).build()).setKey(new ActionKey(actionInfo.getActionKey())).build();
+
+ }
+
+ },
+ set_tcp_source_port {
+
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ String[] actionValues = actionInfo.getActionValues();
+ Integer portNumber = new Integer(actionValues[0]);
+
+ return new ActionBuilder().setAction(
+ new SetFieldCaseBuilder().setSetField(
+ new SetFieldBuilder().setLayer4Match(
+ new TcpMatchBuilder().setTcpSourcePort(
+ new PortNumber(portNumber)).build())
+ .build()).build()).setKey(new ActionKey(actionInfo.getActionKey())).build();
+
+ }
+
+ },
+ set_source_ip {
+
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ String[] actionValues = actionInfo.getActionValues();
+ InetAddress sourceIp = null;
+ try{
+ sourceIp = InetAddress.getByName(actionValues[0]);
+ } catch (Exception e){
+ e.printStackTrace();
+ }
+ return new ActionBuilder().setAction(
+ new SetFieldCaseBuilder().setSetField(
+ new SetFieldBuilder().setLayer3Match(
+ new Ipv4MatchBuilder().setIpv4Source(
+ new Ipv4Prefix(sourceIp.getHostAddress() + "/" + actionValues[1])).build()).
+ build()).build()).setKey(new ActionKey(actionInfo.getActionKey())).build();
+
+ }
+
+ },
+ set_destination_ip {
+
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ String[] actionValues = actionInfo.getActionValues();
+ InetAddress sourceIp = null;
+ try{
+ sourceIp = InetAddress.getByName(actionValues[0]);
+ } catch (Exception e){
+ e.printStackTrace();
+ }
+ return new ActionBuilder().setAction(
+ new SetFieldCaseBuilder().setSetField(
+ new SetFieldBuilder().setLayer3Match(
+ new Ipv4MatchBuilder().setIpv4Destination(
+ new Ipv4Prefix(sourceIp.getHostAddress() + "/" + actionValues[1])).build()).
+ build()).build()).setKey(new ActionKey(actionInfo.getActionKey())).build();
+
+ }
+
+ },
+ set_field_eth_src {
+
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ String[] actionValues = actionInfo.getActionValues();
+ MacAddress mac = new MacAddress(actionValues[0]);
+
+ return new ActionBuilder().setAction(
+ new SetFieldCaseBuilder().setSetField(
+ new SetFieldBuilder().setEthernetMatch(
+ new EthernetMatchBuilder().setEthernetSource(
+ new EthernetSourceBuilder().setAddress(mac).build()).build())
+ .build()).build()).setKey(new ActionKey(actionInfo.getActionKey())).build();
+
+ }
+ },
+
+ drop_action {
+
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ DropActionBuilder dab = new DropActionBuilder();
+ 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();
+ }
+ },
+
+ nx_resubmit {
+
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ String[] actionValues = actionInfo.getActionValues();
+ NxResubmitBuilder nxarsb = new NxResubmitBuilder();
+ nxarsb.setTable(Short.parseShort(actionValues[0]));
+ ActionBuilder ab = new ActionBuilder();
+ ab.setAction(new NxActionResubmitRpcAddGroupCaseBuilder().setNxResubmit(nxarsb.build()).build());
+ ab.setKey(new ActionKey(actionInfo.getActionKey()));
+ return ab.build();
+ }
+ },
+
+ goto_table {
+
+ @Override
+ public Action buildAction(ActionInfo actionInfo) {
+ ActionBuilder ab = new ActionBuilder();
+ return null;
+ }
+ };
+
+ private static final int RADIX_HEX = 16;
+ public abstract Action buildAction(ActionInfo actionInfo);
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.io.Serializable;
+import java.util.List;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+
+public class BucketInfo implements Serializable {
+ private static final long serialVersionUID = 1L;
+ private final List<ActionInfo> m_listActionInfo;
+ private Integer weight = 0;
+ private Long watchPort = 0xffffffffL;
+ private Long watchGroup = 0xffffffffL;
+
+ public BucketInfo(List<ActionInfo> listActions) {
+ m_listActionInfo = listActions;
+ }
+
+ public BucketInfo(List<ActionInfo> m_listActionInfo, Integer weight, Long watchPort, Long watchGroup) {
+ super();
+ this.m_listActionInfo = m_listActionInfo;
+ this.weight = weight;
+ this.watchPort = watchPort;
+ this.watchGroup = watchGroup;
+ }
+
+ public void buildAndAddActions(List<Action> listActionOut) {
+ int key = 0;
+ if (m_listActionInfo != null) {
+ for (ActionInfo actionInfo : m_listActionInfo) {
+ actionInfo.setActionKey(key++);
+ listActionOut.add(actionInfo.buildAction());
+ }
+ }
+ }
+
+ public void setWeight(Integer bucketWeight) {
+ weight = bucketWeight;
+ }
+
+ public Integer getWeight() {
+ return weight;
+ }
+
+ public List<ActionInfo> getActionInfoList() {
+ return m_listActionInfo;
+ }
+
+ public Long getWatchPort() {
+ return watchPort;
+ }
+
+ public void setWatchPort(Long watchPort) {
+ this.watchPort = watchPort;
+ }
+
+ public Long getWatchGroup() {
+ return watchGroup;
+ }
+
+ public void setWatchGroup(Long watchGroup) {
+ this.watchGroup = watchGroup;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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 java.util.List;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
+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.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags;
+
+public class FlowEntity extends AbstractSwitchEntity {
+ private static final long serialVersionUID = 1L;
+
+ private short m_shTableId;
+ private String m_sFlowId;
+ private int m_nPriority;
+ private String m_sFlowName;
+ private int m_nIdleTimeOut;
+ private int m_nHardTimeOut;
+ private BigInteger m_biCookie;
+ private List<MatchInfo> m_listMatchInfo;
+ private List<InstructionInfo> m_listInstructionInfo;
+
+ private boolean m_bStrictFlag;
+ private boolean m_bSendFlowRemFlag;
+
+ private transient FlowBuilder m_flowBuilder;
+
+ public FlowEntity(BigInteger dpnId) {
+ super(dpnId);
+ }
+
+ @Override
+ public String toString() {
+ return "FlowEntity [m_shTableId=" + m_shTableId + ", m_sFlowId=" + m_sFlowId + ", m_nPriority=" + m_nPriority
+ + ", m_sFlowName=" + m_sFlowName + ", m_nIdleTimeOut=" + m_nIdleTimeOut + ", m_nHardTimeOut="
+ + m_nHardTimeOut + ", m_biCookie=" + m_biCookie + ", m_listMatchInfo=" + m_listMatchInfo
+ + ", m_listInstructionInfo=" + m_listInstructionInfo + ", m_bStrictFlag=" + m_bStrictFlag
+ + ", m_bSendFlowRemFlag=" + m_bSendFlowRemFlag + ", toString()=" + super.toString() + "]";
+ }
+
+ public BigInteger getCookie() {
+ return m_biCookie;
+ }
+
+ public String getFlowId() {
+ return m_sFlowId;
+ }
+
+ public String getFlowName() {
+ return m_sFlowName;
+ }
+
+ public int getHardTimeOut() {
+ return m_nHardTimeOut;
+ }
+
+ public int getIdleTimeOut() {
+ return m_nIdleTimeOut;
+ }
+
+ public List<InstructionInfo> getInstructionInfoList() {
+ return m_listInstructionInfo;
+ }
+
+ public List<MatchInfo> getMatchInfoList() {
+ return m_listMatchInfo;
+ }
+
+ public int getPriority() {
+ return m_nPriority;
+ }
+
+ public boolean getSendFlowRemFlag() {
+ return m_bSendFlowRemFlag;
+ }
+
+ public boolean getStrictFlag() {
+ return m_bStrictFlag;
+ }
+
+ public short getTableId() {
+ return m_shTableId;
+ }
+
+ public void setCookie(BigInteger biCookie) {
+ m_biCookie = biCookie;
+ m_flowBuilder = null;
+ }
+
+ public FlowBuilder getFlowBuilder() {
+ if (m_flowBuilder == null) {
+ m_flowBuilder = new FlowBuilder();
+
+ m_flowBuilder.setKey(new FlowKey(new FlowId(getFlowId())));
+
+ m_flowBuilder.setTableId(getTableId());
+ m_flowBuilder.setPriority(getPriority());
+ m_flowBuilder.setFlowName(getFlowName());
+ m_flowBuilder.setIdleTimeout(getIdleTimeOut());
+ m_flowBuilder.setHardTimeout(getHardTimeOut());
+ m_flowBuilder.setCookie(new FlowCookie(getCookie()));
+ m_flowBuilder.setMatch(MDSALUtil.buildMatches(getMatchInfoList()));
+ m_flowBuilder.setInstructions(MDSALUtil.buildInstructions(getInstructionInfoList()));
+
+ m_flowBuilder.setStrict(getStrictFlag());
+ // TODO Fix Me
+ //m_flowBuilder.setResyncFlag(getResyncFlag());
+ if (getSendFlowRemFlag()) {
+ m_flowBuilder.setFlags(new FlowModFlags(false, false, false, false, true));
+ }
+
+ m_flowBuilder.setBarrier(false);
+ m_flowBuilder.setInstallHw(true);
+ }
+
+ return m_flowBuilder;
+ }
+
+ public void setFlowId(String sFlowId) {
+ m_sFlowId = sFlowId;
+ if (m_flowBuilder != null) {
+ m_flowBuilder.setKey(new FlowKey(new FlowId(sFlowId)));
+ }
+ }
+
+ public void setFlowName(String sFlowName) {
+ m_sFlowName = sFlowName;
+ m_flowBuilder = null;
+ }
+
+ public void setHardTimeOut(int nHardTimeOut) {
+ m_nHardTimeOut = nHardTimeOut;
+ m_flowBuilder = null;
+ }
+
+ public void setIdleTimeOut(int nIdleTimeOut) {
+ m_nIdleTimeOut = nIdleTimeOut;
+ m_flowBuilder = null;
+ }
+
+ public void setInstructionInfoList(List<InstructionInfo> listInstructionInfo) {
+ m_listInstructionInfo = listInstructionInfo;
+ m_flowBuilder = null;
+ }
+
+ public void setMatchInfoList(List<MatchInfo> listMatchInfo) {
+ m_listMatchInfo = listMatchInfo;
+ m_flowBuilder = null;
+ }
+
+ public void setPriority(int nPriority) {
+ m_nPriority = nPriority;
+ m_flowBuilder = null;
+ }
+
+ public void setSendFlowRemFlag(boolean bSendFlowRemFlag) {
+ m_bSendFlowRemFlag = bSendFlowRemFlag;
+ m_flowBuilder = null;
+ }
+
+ public void setStrictFlag(boolean bStrictFlag) {
+ m_bStrictFlag = bStrictFlag;
+ m_flowBuilder = null;
+ }
+
+ public void setTableId(short shTableId) {
+ m_shTableId = shTableId;
+ m_flowBuilder = 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.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) 2015 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 java.util.List;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
+
+public class GroupEntity extends AbstractSwitchEntity {
+ private static final long serialVersionUID = 1L;
+
+ private long m_lGroupId;
+ private String m_sGroupName;
+ private GroupTypes m_groupType;
+ private List<BucketInfo> m_listBucketInfo;
+
+ private transient GroupBuilder m_groupBuilder;
+
+ public GroupEntity(BigInteger dpnId) {
+ super(dpnId);
+ }
+
+ @Override
+ public String toString() {
+ return "GroupEntity [m_lGroupId=" + m_lGroupId + ", m_sGroupName=" + m_sGroupName + ", m_groupType="
+ + m_groupType + ", m_listBucketInfo=" + m_listBucketInfo + ", toString()=" + super.toString() + "]";
+ }
+
+ public List<BucketInfo> getBucketInfoList() {
+ return m_listBucketInfo;
+ }
+
+ public GroupBuilder getGroupBuilder() {
+ if (m_groupBuilder == null) {
+ m_groupBuilder = new GroupBuilder();
+
+ GroupId groupId = new GroupId(getGroupId());
+ m_groupBuilder.setKey(new GroupKey(groupId));
+ m_groupBuilder.setGroupId(groupId);
+
+ m_groupBuilder.setGroupName(getGroupName());
+ m_groupBuilder.setGroupType(getGroupType());
+ m_groupBuilder.setBuckets(MDSALUtil.buildBuckets(getBucketInfoList()));
+ }
+
+ return m_groupBuilder;
+ }
+
+ public long getGroupId() {
+ return m_lGroupId;
+ }
+
+ public String getGroupName() {
+ return m_sGroupName;
+ }
+
+ public GroupTypes getGroupType() {
+ return m_groupType;
+ }
+
+ public void setBucketInfoList(List<BucketInfo> listBucketInfo) {
+ m_listBucketInfo = listBucketInfo;
+ }
+
+ public void setGroupId(long lGroupId) {
+ m_lGroupId = lGroupId;
+ if (m_groupBuilder != null) {
+ GroupId groupId = new GroupId(getGroupId());
+ m_groupBuilder.setKey(new GroupKey(groupId));
+ m_groupBuilder.setGroupId(groupId);
+ }
+ }
+
+ public void setGroupName(String sGroupName) {
+ m_sGroupName = sGroupName;
+ m_groupBuilder = null;
+ }
+
+ public void setGroupType(GroupTypes groupType) {
+ m_groupType = groupType;
+ m_groupBuilder = 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.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 + "]";
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.io.Serializable;
+import java.math.BigInteger;
+import java.util.List;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+
+public class InstructionInfo implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private final InstructionType m_instructionType;
+ private long[] m_alInstructionValues;
+ private BigInteger[] m_alBigInstructionValues;
+ private List<ActionInfo> m_actionInfos;
+
+ // This constructor should be used incase of clearAction
+ public InstructionInfo(InstructionType instructionType) {
+ m_instructionType = instructionType;
+ }
+
+ public InstructionInfo(InstructionType instructionType, long[] instructionValues) {
+ m_instructionType = instructionType;
+ m_alInstructionValues = instructionValues;
+ }
+
+ public InstructionInfo(InstructionType instructionType, BigInteger[] instructionValues) {
+ m_instructionType = instructionType;
+ m_alBigInstructionValues = instructionValues;
+ }
+
+ public InstructionInfo(InstructionType instructionType, List<ActionInfo> actionInfos) {
+ m_instructionType = instructionType;
+ m_actionInfos = actionInfos;
+ }
+
+ public Instruction buildInstruction(int instructionKey) {
+ return m_instructionType.buildInstruction(this, instructionKey);
+ }
+
+ public InstructionType getInstructionType() {
+ return m_instructionType;
+ }
+
+ public long[] getInstructionValues() {
+ return m_alInstructionValues;
+ }
+
+ public BigInteger[] getBigInstructionValues() {
+ return m_alBigInstructionValues;
+ }
+
+ public List<ActionInfo> getActionInfos() {
+ return m_actionInfos;
+ }
+
+ public void setInstructionValues(long[] m_alInstructionValues) {
+ this.m_alInstructionValues = m_alInstructionValues;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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 java.util.ArrayList;
+import java.util.List;
+
+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.instruction.instruction.ApplyActionsCase;
+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.GoToTableCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.ClearActionsCaseBuilder;
+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.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.actions._case.WriteActions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.actions._case.WriteActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+
+public enum InstructionType {
+ apply_actions {
+ @Override
+ public Instruction buildInstruction(InstructionInfo instructionInfo, int instructionKey) {
+ List<ActionInfo> mkActions = instructionInfo.getActionInfos();
+ List<Action> listAction = new ArrayList <Action> ();
+ int actionKey = 0 ;
+ for(ActionInfo mkAction: mkActions) {
+ ActionType actionType = mkAction.getActionType();
+ mkAction.setActionKey(actionKey++);
+ listAction.add(actionType.buildAction(mkAction));
+ }
+ ApplyActions applyActions = new ApplyActionsBuilder().setAction(listAction).build();
+ ApplyActionsCase applyActionsCase = new ApplyActionsCaseBuilder().setApplyActions(applyActions).build();
+ InstructionBuilder instructionBuilder = new InstructionBuilder();
+
+ instructionBuilder.setInstruction(applyActionsCase);
+ instructionBuilder.setKey(new InstructionKey(instructionKey));
+
+ return instructionBuilder.build();
+ }
+ },
+
+ goto_table {
+ @Override
+ public Instruction buildInstruction(InstructionInfo instructionInfo, int instructionKey) {
+ short tableId = (short) instructionInfo.getInstructionValues()[0];
+
+ return new InstructionBuilder()
+ .setInstruction(
+ new GoToTableCaseBuilder().setGoToTable(
+ new GoToTableBuilder().setTableId(Short.valueOf(tableId)).build()).build())
+ .setKey(new InstructionKey(instructionKey)).build();
+ }
+ },
+
+ write_actions {
+ @Override
+ public Instruction buildInstruction(InstructionInfo instructionInfo, int instructionKey) {
+ List<ActionInfo> mkActions = instructionInfo.getActionInfos();
+ List<Action> listAction = new ArrayList <Action> ();
+ int actionKey = 0 ;
+ for(ActionInfo mkAction: mkActions) {
+ ActionType actionType = mkAction.getActionType();
+ mkAction.setActionKey(actionKey++);
+ listAction.add(actionType.buildAction(mkAction));
+ }
+ WriteActions writeActions = new WriteActionsBuilder().setAction(listAction).build();
+ WriteActionsCase writeActionsCase = new WriteActionsCaseBuilder().setWriteActions(writeActions).build();
+ InstructionBuilder instructionBuilder = new InstructionBuilder();
+
+ instructionBuilder.setInstruction(writeActionsCase);
+ instructionBuilder.setKey(new InstructionKey(instructionKey));
+
+ return instructionBuilder.build();
+ }
+ },
+
+ clear_actions {
+ @Override
+ public Instruction buildInstruction(InstructionInfo instructionInfo, int instructionKey) {
+
+ ClearActionsCase clearActionsCase = new ClearActionsCaseBuilder().build();
+
+ InstructionBuilder instructionBuilder = new InstructionBuilder();
+ instructionBuilder.setInstruction(clearActionsCase);
+ instructionBuilder.setKey(new InstructionKey(instructionKey));
+
+ return instructionBuilder.build();
+ }
+ },
+
+ write_metadata {
+ @Override
+ public Instruction buildInstruction(InstructionInfo instructionInfo, int instructionKey) {
+ BigInteger[] metadataValues = instructionInfo.getBigInstructionValues();
+ BigInteger metadata = metadataValues[0];
+ BigInteger mask = metadataValues[1];
+
+ return new InstructionBuilder()
+ .setInstruction(
+ new WriteMetadataCaseBuilder().setWriteMetadata(
+ new WriteMetadataBuilder().setMetadata(metadata).setMetadataMask(mask).build())
+ .build()).setKey(new InstructionKey(instructionKey)).build();
+ }
+ };
+
+ public abstract Instruction buildInstruction(InstructionInfo instructionInfo, int instructionKey);
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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 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.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class MDSALDataStoreUtils {
+
+ public static <T extends DataObject> Optional<T> read(final DataBroker broker,final 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 asyncWrite(final DataBroker broker, final LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.put(datastoreType, path, data, true);
+ Futures.addCallback(tx.submit(), callback);
+ }
+
+ public static <T extends DataObject> void asyncUpdate(final DataBroker broker,final LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.merge(datastoreType, path, data, true);
+ Futures.addCallback(tx.submit(), callback);
+ }
+
+ public static <T extends DataObject> void asyncRemove(final DataBroker broker,final LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.delete(datastoreType, path);
+ Futures.addCallback(tx.submit(), callback);
+ }
+
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.vpnservice.mdsalutil;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.LinkedBlockingQueue;
+
+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.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.PopVlanActionCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.SetFieldCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.pop.vlan.action._case.PopVlanActionBuilder;
+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.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.FlowCookie;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+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.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowModFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+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.instruction.ApplyActionsCase;
+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.GoToTableCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteActionsCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.WriteMetadataCaseBuilder;
+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.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.go.to.table._case.GoToTableBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.actions._case.WriteActions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.actions._case.WriteActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.write.metadata._case.WriteMetadataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.BucketId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+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.model.match.types.rev131026.match.TunnelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.controller.liblldp.HexEncode;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import com.google.common.primitives.Bytes;
+import com.google.common.primitives.Ints;
+import com.google.common.util.concurrent.CheckedFuture;
+
+public class MDSALUtil {
+
+ public enum MdsalOp { CREATION_OP, UPDATE_OP, REMOVAL_OP };
+
+ public static final String NODE_PREFIX = "openflow";
+ public static final int GROUP_WEIGHT = 0;
+ public static final long WATCH_PORT = 0xffffffffL;
+ public static final long WATCH_GROUP = 0xffffffffL;
+ public static final String SEPARATOR = ":";
+ private static final Buckets EMPTY_Buckets = new BucketsBuilder().build();
+ private static final Instructions EMPTY_Instructions = new InstructionsBuilder().setInstruction(
+ new ArrayList<Instruction>()).build();
+ private static final Match EMPTY_Matches = new MatchBuilder().build();
+ private static final Logger logger = LoggerFactory.getLogger(MDSALUtil.class);
+
+ public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, String flowId, int priority, String flowName,
+ int idleTimeOut, int hardTimeOut, BigInteger cookie, List<MatchInfo> listMatchInfo,
+ List<InstructionInfo> listInstructionInfo) {
+
+ FlowEntity flowEntity = new FlowEntity(dpnId);
+
+ flowEntity.setTableId(tableId);
+ flowEntity.setFlowId(flowId);
+ flowEntity.setPriority(priority);
+ flowEntity.setFlowName(flowName);
+ flowEntity.setIdleTimeOut(idleTimeOut);
+ flowEntity.setHardTimeOut(hardTimeOut);
+ flowEntity.setCookie(cookie);
+ flowEntity.setMatchInfoList(listMatchInfo);
+ flowEntity.setInstructionInfoList(listInstructionInfo);
+
+ return flowEntity;
+ }
+
+ // TODO: CHECK IF THIS IS USED
+ public static Flow buildFlow(short tableId, String flowId, int priority, String flowName, int idleTimeOut,
+ int hardTimeOut, BigInteger cookie, List<MatchInfo> listMatchInfo, List<InstructionInfo> listInstructionInfo) {
+ return MDSALUtil.buildFlow(tableId, flowId, priority, flowName, idleTimeOut, hardTimeOut, cookie,
+ listMatchInfo, listInstructionInfo, true);
+ }
+
+ public static Flow buildFlow(short tableId, String flowId, int priority, String flowName, int idleTimeOut,
+ int hardTimeOut, BigInteger cookie, List<MatchInfo> listMatchInfo,
+ List<InstructionInfo> listInstructionInfo, boolean isStrict) {
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ return new FlowBuilder().setMatch(buildMatches(listMatchInfo)).setKey(key)
+ .setPriority(Integer.valueOf(priority)).setInstructions(buildInstructions(listInstructionInfo))
+ .setBarrier(false).setInstallHw(true).setHardTimeout(hardTimeOut).setIdleTimeout(idleTimeOut)
+ .setFlowName(flowName).setTableId(Short.valueOf(tableId)).setStrict(isStrict)
+ .setCookie(new FlowCookie(cookie)).build();
+ }
+
+ public static Flow buildFlow(short tableId, String flowId) {
+ return new FlowBuilder().setTableId(tableId).setId(new FlowId(flowId)).build();
+ }
+
+ public static Flow buildFlowNew(short tableId, String flowId, int priority, String flowName, int idleTimeOut,
+ int hardTimeOut, BigInteger cookie, List<MatchInfo> listMatchInfo, List<Instruction> listInstructionInfo) {
+ return MDSALUtil.buildFlowNew(tableId, flowId, priority, flowName, idleTimeOut, hardTimeOut, cookie,
+ listMatchInfo, listInstructionInfo, true);
+ }
+
+ private static Flow buildFlowNew(short tableId, String flowId, int priority, String flowName, int idleTimeOut,
+ int hardTimeOut, BigInteger cookie, List<MatchInfo> listMatchInfo,
+ List<Instruction> listInstructionInfo, boolean isStrict) {
+ FlowKey key = new FlowKey(new FlowId(flowId));
+ return new FlowBuilder().setMatch(buildMatches(listMatchInfo)).setKey(key)
+ .setPriority(Integer.valueOf(priority)).setInstructions(new InstructionsBuilder().setInstruction(listInstructionInfo).build())
+ .setBarrier(false).setInstallHw(true).setHardTimeout(hardTimeOut).setIdleTimeout(idleTimeOut)
+ .setFlowName(flowName).setTableId(Short.valueOf(tableId)).setStrict(isStrict)
+ .setCookie(new FlowCookie(cookie)).build();
+ }
+
+ public static GroupEntity buildGroupEntity(BigInteger dpnId, long groupId, String groupName, GroupTypes groupType,
+ List<BucketInfo> listBucketInfo) {
+
+ GroupEntity groupEntity = new GroupEntity(dpnId);
+
+ groupEntity.setGroupId(groupId);
+ groupEntity.setGroupName(groupName);
+ groupEntity.setGroupType(groupType);
+ groupEntity.setBucketInfoList(listBucketInfo);
+
+ return groupEntity;
+ }
+
+ public static Group buildGroup(long groupId, String groupName, GroupTypes groupType, Buckets buckets) {
+ GroupId groupIdentifier = new GroupId(groupId);
+ return new GroupBuilder().setGroupId(groupIdentifier).setKey(new GroupKey(groupIdentifier)).setGroupName(groupName)
+ .setGroupType(groupType).setBuckets(buckets).build();
+ }
+
+ public static TransmitPacketInput getPacketOutDefault(List<ActionInfo> actionInfos, byte[] payload, BigInteger dpnId) {
+ return new TransmitPacketInputBuilder()
+ .setAction(buildActions(actionInfos))
+ .setPayload(payload)
+ .setNode(
+ new NodeRef(InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, new NodeKey(new NodeId("openflow:" + dpnId))).toInstance()))
+ .setIngress(getDefaultNodeConnRef(dpnId)).setEgress(getDefaultNodeConnRef(dpnId)).build();
+ }
+
+ public static TransmitPacketInput getPacketOut(List<ActionInfo> actionInfos, byte[] payload, long dpnId,
+ NodeConnectorRef ingress) {
+ return new TransmitPacketInputBuilder()
+ .setAction(buildActions(actionInfos))
+ .setPayload(payload)
+ .setNode(
+ new NodeRef(InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, new NodeKey(new NodeId("openflow:" + dpnId))).toInstance()))
+ .setIngress(ingress).setEgress(ingress).build();
+ }
+
+ public static Action retrieveSetTunnelIdAction(BigInteger tunnelId, int actionKey) {
+ return new ActionBuilder().setAction(
+ new SetFieldCaseBuilder().setSetField(new SetFieldBuilder().setTunnel(new TunnelBuilder()
+ .setTunnelId(tunnelId).build()).build())
+ .build()).setKey(new ActionKey(actionKey)).build();
+ }
+
+ public static List<Action> buildActions(List<ActionInfo> actions) {
+ List<Action> actionsList = new ArrayList<Action>();
+ for (ActionInfo actionInfo : actions) {
+ actionsList.add(actionInfo.buildAction());
+ }
+ return actionsList;
+ }
+
+ public static String longToIp(long ip, long mask) {
+ StringBuilder sb = new StringBuilder(15);
+ Joiner joiner = Joiner.on('.');
+
+ joiner.appendTo(sb, Bytes.asList(Ints.toByteArray((int) ip)));
+
+ sb.append("/" + mask);
+
+ return sb.toString();
+ }
+
+
+ public static Bucket buildBucket(List<Action> actionsList, int weight, int bucketId, long watchPort, long watchGroup) {
+ return new BucketBuilder().setAction(actionsList).setWeight(weight)
+ .setWatchGroup(watchGroup).setWatchPort(watchPort).setBucketId(new BucketId(Long.valueOf(bucketId))).setKey(new BucketKey(new BucketId(Long.valueOf(bucketId)))).build();
+
+ }
+
+ public static Buckets buildBucketLists(List<Bucket> bucketList) {
+ return new BucketsBuilder().setBucket(bucketList).build();
+ }
+
+ protected static Buckets buildBuckets(List<BucketInfo> listBucketInfo) {
+ long i = 0;
+ if (listBucketInfo != null) {
+ BucketsBuilder bucketsBuilder = new BucketsBuilder();
+ List<Bucket> bucketList = new ArrayList<Bucket>();
+
+ for (BucketInfo bucketInfo : listBucketInfo) {
+ BucketBuilder bucketBuilder = new BucketBuilder();
+ List<Action> actionsList = new ArrayList<Action>();
+
+ bucketInfo.buildAndAddActions(actionsList);
+ bucketBuilder.setAction(actionsList);
+ bucketBuilder.setWeight(bucketInfo.getWeight());
+ bucketBuilder.setBucketId(new BucketId(i++));
+ bucketBuilder.setWeight(bucketInfo.getWeight()).setWatchPort(bucketInfo.getWatchPort())
+ .setWatchGroup(bucketInfo.getWatchGroup());
+ bucketList.add(bucketBuilder.build());
+ }
+
+ bucketsBuilder.setBucket(bucketList);
+ return bucketsBuilder.build();
+ }
+
+ return EMPTY_Buckets;
+ }
+
+ public static Instructions buildInstructions(List<InstructionInfo> listInstructionInfo) {
+ if (listInstructionInfo != null) {
+ List<Instruction> instructions = new ArrayList<Instruction>();
+ int instructionKey = 0;
+
+ for (InstructionInfo instructionInfo : listInstructionInfo) {
+ instructions.add(instructionInfo.buildInstruction(instructionKey));
+ instructionKey++;
+ }
+
+ return new InstructionsBuilder().setInstruction(instructions).build();
+ }
+
+ return EMPTY_Instructions;
+ }
+
+ public static Match buildMatches(List<MatchInfo> listMatchInfo) {
+ if (listMatchInfo != null) {
+ MatchBuilder matchBuilder = new MatchBuilder();
+ Map<Class<?>, Object> mapMatchBuilder = new HashMap<Class<?>, Object>();
+
+ for (MatchInfo matchInfo : listMatchInfo) {
+ matchInfo.createInnerMatchBuilder(mapMatchBuilder);
+ }
+
+ for (MatchInfo matchInfo : listMatchInfo) {
+ matchInfo.setMatch(matchBuilder, mapMatchBuilder);
+ }
+
+ return matchBuilder.build();
+ }
+
+ return EMPTY_Matches;
+ }
+
+ // TODO: Check the port const
+ public static NodeConnectorRef getDefaultNodeConnRef(BigInteger nDpId) {
+ return getNodeConnRef(NODE_PREFIX + SEPARATOR + nDpId, "0xfffffffd");
+ }
+
+ public static NodeConnectorRef getNodeConnRef(BigInteger nDpId, String port) {
+ return getNodeConnRef(NODE_PREFIX + SEPARATOR + nDpId, port);
+ }
+
+ public static NodeConnectorRef getNodeConnRef(String sNodeId, String port) {
+ String sNodeConnectorKey;
+ StringBuilder sbTmp;
+ NodeId nodeId;
+ NodeKey nodeKey;
+ NodeConnectorId nodeConnectorId;
+ NodeConnectorKey nodeConnectorKey;
+ InstanceIdentifierBuilder<Nodes> nodesInstanceIdentifierBuilder;
+ InstanceIdentifierBuilder<Node> nodeInstanceIdentifierBuilder;
+ InstanceIdentifierBuilder<NodeConnector> nodeConnectorInstanceIdentifierBuilder;
+ InstanceIdentifier<NodeConnector> nodeConnectorInstanceIdentifier;
+ NodeConnectorRef nodeConnectorRef;
+
+ sbTmp = new StringBuilder();
+
+ sbTmp.append(sNodeId);
+ sbTmp.append(SEPARATOR);
+ sbTmp.append(port);
+
+ sNodeConnectorKey = sbTmp.toString();
+ nodeConnectorId = new NodeConnectorId(sNodeConnectorKey);
+ nodeConnectorKey = new NodeConnectorKey(nodeConnectorId);
+
+ nodeId = new NodeId(sNodeId);
+ nodeKey = new NodeKey(nodeId);
+
+ nodesInstanceIdentifierBuilder = InstanceIdentifier.<Nodes> builder(Nodes.class);
+ nodeInstanceIdentifierBuilder = nodesInstanceIdentifierBuilder.<Node, NodeKey> child(Node.class, nodeKey);
+ nodeConnectorInstanceIdentifierBuilder = nodeInstanceIdentifierBuilder.<NodeConnector, NodeConnectorKey> child(
+ NodeConnector.class, nodeConnectorKey);
+ nodeConnectorInstanceIdentifier = nodeConnectorInstanceIdentifierBuilder.toInstance();
+ nodeConnectorRef = new NodeConnectorRef(nodeConnectorInstanceIdentifier);
+ return nodeConnectorRef;
+ }
+
+ public static BigInteger getDpnIdFromNodeName(NodeId nodeId) {
+ return getDpnIdFromNodeName(nodeId.getValue());
+ }
+
+ public static BigInteger getDpnIdFromNodeName(String sMdsalNodeName) {
+ String sDpId = sMdsalNodeName.substring(sMdsalNodeName.lastIndexOf(":") + 1);
+ return new BigInteger(sDpId);
+ }
+
+ public static long getOfPortNumberFromPortName(NodeConnectorId nodeConnectorId) {
+ return getOfPortNumberFromPortName(nodeConnectorId.getValue());
+ }
+
+ public static long getDpnIdFromPortName(NodeConnectorId nodeConnectorId) {
+ String ofPortName = nodeConnectorId.getValue();
+ return Long.parseLong(ofPortName.substring(ofPortName.indexOf(":")+1,
+ ofPortName.lastIndexOf(":")));
+ }
+
+ public static long getOfPortNumberFromPortName(String sMdsalPortName) {
+ String sPortNumber = sMdsalPortName.substring(sMdsalPortName.lastIndexOf(":") + 1);
+ return Long.parseLong(sPortNumber);
+ }
+
+ public static TransmitPacketInput getPacketOut(List<ActionInfo> actionInfos, byte[] payload, BigInteger dpnId,
+ NodeConnectorRef nodeConnRef) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public static Instruction buildAndGetPopVlanActionInstruction(int actionKey, int instructionKey) {
+ Action popVlanAction = new ActionBuilder().setAction(
+ new PopVlanActionCaseBuilder().setPopVlanAction(new PopVlanActionBuilder().build()).build())
+ .setKey(new ActionKey(actionKey)).build();
+ List<Action> listAction = new ArrayList<Action> ();
+ listAction.add(popVlanAction);
+ return buildApplyActionsInstruction(listAction, instructionKey);
+ }
+
+ public static Instruction buildApplyActionsInstruction(List<Action> actions) {
+ return buildApplyActionsInstruction(actions, 0);
+ }
+
+ public static Instruction buildApplyActionsInstruction(List<Action> listAction, int instructionKey) {
+ ApplyActions applyActions = new ApplyActionsBuilder().setAction(listAction).build();
+ ApplyActionsCase applyActionsCase = new ApplyActionsCaseBuilder().setApplyActions(applyActions).build();
+ InstructionBuilder instructionBuilder = new InstructionBuilder();
+
+ instructionBuilder.setInstruction(applyActionsCase);
+ instructionBuilder.setKey(new InstructionKey(instructionKey));
+ return instructionBuilder.build();
+ }
+
+ public static List<Instruction> buildInstructionsDrop() {
+ return buildInstructionsDrop(0);
+ }
+
+ public static List<Instruction> buildInstructionsDrop(int instructionKey) {
+ List<Instruction> mkInstructions = new ArrayList<Instruction>();
+ List <Action> actionsInfos = new ArrayList <Action> ();
+ actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[]{}).buildAction());
+ mkInstructions.add(getWriteActionsInstruction(actionsInfos, instructionKey));
+ return mkInstructions;
+ }
+
+
+ public static Instruction getWriteActionsInstruction(List<Action> listAction, int instructionKey) {
+ WriteActions writeActions = new WriteActionsBuilder().setAction(listAction).build();
+ WriteActionsCase writeActionsCase = new WriteActionsCaseBuilder().setWriteActions(writeActions).build();
+ InstructionBuilder instructionBuilder = new InstructionBuilder();
+
+ instructionBuilder.setInstruction(writeActionsCase);
+ instructionBuilder.setKey(new InstructionKey(instructionKey));
+ return instructionBuilder.build();
+ }
+
+ public static Action buildAction(int actionKey, int instruction) {
+ return new ActionBuilder().setAction(
+ new PopVlanActionCaseBuilder().setPopVlanAction(new PopVlanActionBuilder().build()).build())
+ .setKey(new ActionKey(actionKey)).build();
+ }
+
+ public static Instruction buildAndGetWriteMetadaInstruction(BigInteger metadata,
+ BigInteger mask, int instructionKey) {
+ return new InstructionBuilder()
+ .setInstruction(
+ new WriteMetadataCaseBuilder().setWriteMetadata(
+ new WriteMetadataBuilder().setMetadata(metadata).setMetadataMask(mask).build())
+ .build()).setKey(new InstructionKey(instructionKey)).build();
+ }
+
+ public static Instruction buildAndGetGotoTableInstruction(short tableId, int instructionKey) {
+ return new InstructionBuilder()
+ .setInstruction(
+ new GoToTableCaseBuilder().setGoToTable(
+ new GoToTableBuilder().setTableId(tableId).build()).build())
+ .setKey(new InstructionKey(instructionKey)).build();
+ }
+
+ public static <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, DataBroker broker) {
+
+ ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
+
+ Optional<T> result = Optional.absent();
+ try {
+ result = tx.read(datastoreType, path).get();
+ } catch (Exception e) {
+ logger.error("An error occured while reading data from the path {} with the exception {}", path, e);
+ }
+ return result;
+ }
+
+ 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 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 <T extends DataObject> void syncUpdate(DataBroker broker,
+ LogicalDatastoreType datastoreType, InstanceIdentifier<T> path,
+ T data) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.merge(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 <T extends DataObject> void syncDelete(DataBroker broker,
+ LogicalDatastoreType datastoreType, InstanceIdentifier<T> obj) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.delete(datastoreType, obj);
+ CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+ try {
+ futures.get();
+ } catch (InterruptedException | ExecutionException e) {
+ logger.error("Error deleting from datastore (path) : ({})", obj);
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+
+ public static byte[] getMacAddressForNodeConnector(DataBroker broker,
+ InstanceIdentifier<NodeConnector> nodeConnectorId) {
+ Optional<NodeConnector> optNc = MDSALDataStoreUtils.read(broker,
+ LogicalDatastoreType.OPERATIONAL, nodeConnectorId);
+ if(optNc.isPresent()) {
+ NodeConnector nc = optNc.get();
+ FlowCapableNodeConnector fcnc = nc.getAugmentation(FlowCapableNodeConnector.class);
+ MacAddress macAddress = fcnc.getHardwareAddress();
+ return HexEncode.bytesFromHexString(macAddress.getValue());
+ }
+ return null;
+ }
+
+ public static NodeId getNodeIdFromNodeConnectorId(NodeConnectorId ncId) {
+ return new NodeId(ncId.getValue().substring(0,
+ ncId.getValue().lastIndexOf(":")));
+ }
+
+ public static String getInterfaceName(NodeConnectorRef ref, DataBroker dataBroker) {
+ NodeConnectorId nodeConnectorId = getNodeConnectorId(dataBroker, ref);
+ NodeId nodeId = getNodeIdFromNodeConnectorId(nodeConnectorId);
+ InstanceIdentifier<NodeConnector> ncIdentifier = InstanceIdentifier
+ .builder(Nodes.class)
+ .child(Node.class, new NodeKey(nodeId))
+ .child(NodeConnector.class,
+ new NodeConnectorKey(nodeConnectorId)).build();
+
+ Optional<NodeConnector> nodeConnectorOptional = read(
+ dataBroker,
+ LogicalDatastoreType.OPERATIONAL, ncIdentifier);
+ if (!nodeConnectorOptional.isPresent()) {
+ return null;
+ }
+ NodeConnector nc = nodeConnectorOptional.get();
+ FlowCapableNodeConnector fc = nc
+ .getAugmentation(FlowCapableNodeConnector.class);
+ return fc.getName();
+ }
+
+ public static NodeConnectorId getNodeConnectorId(DataBroker dataBroker,
+ NodeConnectorRef ref) {
+ Optional<NodeConnector> nc = (Optional<NodeConnector>) read(
+ dataBroker,
+ LogicalDatastoreType.OPERATIONAL, ref.getValue());
+ if(nc.isPresent()){
+ return nc.get().getId();
+ }
+ return null;
+ }
+
+ public static TransmitPacketInput getPacketOut(List<Action> actions, byte[] payload, BigInteger dpnId) {
+ NodeConnectorRef ncRef = getDefaultNodeConnRef(dpnId);
+ return new TransmitPacketInputBuilder()
+ .setAction(actions)
+ .setPayload(payload)
+ .setNode(
+ new NodeRef(InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, new NodeKey(new NodeId("openflow:" + dpnId))).toInstance()))
+ .setIngress(ncRef).setEgress(ncRef).build();
+ }
+
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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 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.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
+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.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
+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.ethernet.match.fields.EthernetSourceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
+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.IpMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.MetadataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.ProtocolMatchFieldsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
+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.TcpMatchBuilder;
+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.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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.EthDst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.EthSrc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.EthType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.InPort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.IpProto;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Ipv4Dst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Ipv4Src;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.MatchField;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.Metadata;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.MplsLabel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.PbbIsid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TcpDst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TcpSrc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.UdpDst;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.UdpSrc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.VlanVid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TunnelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.TunnelId;
+
+public enum MatchFieldType {
+ eth_src {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return EthSrc.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ EthernetMatchBuilder ethernetMatchBuilder = (EthernetMatchBuilder) mapMatchBuilder
+ .get(EthernetMatchBuilder.class);
+
+ if (ethernetMatchBuilder == null) {
+ ethernetMatchBuilder = new EthernetMatchBuilder();
+ mapMatchBuilder.put(EthernetMatchBuilder.class, ethernetMatchBuilder);
+ }
+
+ ethernetMatchBuilder.setEthernetSource(new EthernetSourceBuilder().setAddress(
+ new MacAddress(matchInfo.getStringMatchValues()[0])).build());
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ EthernetMatchBuilder ethernetMatchBuilder = (EthernetMatchBuilder) mapMatchBuilder
+ .remove(EthernetMatchBuilder.class);
+
+ if (ethernetMatchBuilder != null) {
+ matchBuilderInOut.setEthernetMatch(ethernetMatchBuilder.build());
+ }
+ }
+ },
+
+ eth_dst {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return EthDst.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ EthernetMatchBuilder ethernetMatchBuilder = (EthernetMatchBuilder) mapMatchBuilder
+ .get(EthernetMatchBuilder.class);
+
+ if (ethernetMatchBuilder == null) {
+ ethernetMatchBuilder = new EthernetMatchBuilder();
+ mapMatchBuilder.put(EthernetMatchBuilder.class, ethernetMatchBuilder);
+ }
+
+ ethernetMatchBuilder.setEthernetDestination(new EthernetDestinationBuilder().setAddress(
+ new MacAddress(matchInfo.getStringMatchValues()[0])).build());
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ EthernetMatchBuilder ethernetMatchBuilder = (EthernetMatchBuilder) mapMatchBuilder
+ .remove(EthernetMatchBuilder.class);
+
+ if (ethernetMatchBuilder != null) {
+ matchBuilderInOut.setEthernetMatch(ethernetMatchBuilder.build());
+ }
+ }
+ },
+
+ eth_type {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return EthType.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ EthernetMatchBuilder ethernetMatchBuilder = (EthernetMatchBuilder) mapMatchBuilder
+ .get(EthernetMatchBuilder.class);
+
+ if (ethernetMatchBuilder == null) {
+ ethernetMatchBuilder = new EthernetMatchBuilder();
+ mapMatchBuilder.put(EthernetMatchBuilder.class, ethernetMatchBuilder);
+ }
+
+ ethernetMatchBuilder.setEthernetType(new EthernetTypeBuilder().setType(
+ new EtherType(matchInfo.getMatchValues()[0])).build());
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ EthernetMatchBuilder ethernetMatchBuilder = (EthernetMatchBuilder) mapMatchBuilder
+ .remove(EthernetMatchBuilder.class);
+
+ if (ethernetMatchBuilder != null) {
+ matchBuilderInOut.setEthernetMatch(ethernetMatchBuilder.build());
+ }
+ }
+ },
+
+ in_port {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return InPort.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+
+ StringBuffer nodeConnectorId = new StringBuffer().append("openflow:").append(matchInfo.getBigMatchValues()[0])
+ .append(':').append(matchInfo.getBigMatchValues()[1]);
+ matchBuilderInOut.setInPort(new NodeConnectorId(nodeConnectorId.toString()));
+ }
+ },
+
+ ip_proto {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return IpProto.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ IpMatchBuilder ipMatchBuilder = (IpMatchBuilder) mapMatchBuilder.get(IpMatchBuilder.class);
+
+ if (ipMatchBuilder == null) {
+ ipMatchBuilder = new IpMatchBuilder();
+ mapMatchBuilder.put(IpMatchBuilder.class, ipMatchBuilder);
+ }
+
+ ipMatchBuilder.setIpProtocol(Short.valueOf((short) matchInfo.getMatchValues()[0])).build();
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ IpMatchBuilder ipMatchBuilder = (IpMatchBuilder) mapMatchBuilder.remove(IpMatchBuilder.class);
+
+ if (ipMatchBuilder != null) {
+ matchBuilderInOut.setIpMatch(ipMatchBuilder.build());
+ }
+ }
+ },
+
+ ipv4_dst {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return Ipv4Dst.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ Ipv4MatchBuilder ipv4MatchBuilder = (Ipv4MatchBuilder) mapMatchBuilder.get(Ipv4MatchBuilder.class);
+
+ if (ipv4MatchBuilder == null) {
+ ipv4MatchBuilder = new Ipv4MatchBuilder();
+ mapMatchBuilder.put(Ipv4MatchBuilder.class, ipv4MatchBuilder);
+ }
+
+ long[] prefix = matchInfo.getMatchValues();
+ ipv4MatchBuilder.setIpv4Destination(new Ipv4Prefix(MDSALUtil.longToIp(prefix[0], prefix[1]))).build();
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ Ipv4MatchBuilder ipv4MatchBuilder = (Ipv4MatchBuilder) mapMatchBuilder.remove(Ipv4MatchBuilder.class);
+
+ if (ipv4MatchBuilder != null) {
+ matchBuilderInOut.setLayer3Match(ipv4MatchBuilder.build());
+ }
+ }
+ },
+
+ ipv4_src {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return Ipv4Src.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ Ipv4MatchBuilder ipv4MatchBuilder = (Ipv4MatchBuilder) mapMatchBuilder.get(Ipv4MatchBuilder.class);
+
+ if (ipv4MatchBuilder == null) {
+ ipv4MatchBuilder = new Ipv4MatchBuilder();
+ mapMatchBuilder.put(Ipv4MatchBuilder.class, ipv4MatchBuilder);
+ }
+
+ long[] prefix = matchInfo.getMatchValues();
+ ipv4MatchBuilder.setIpv4Source(new Ipv4Prefix(MDSALUtil.longToIp(prefix[0], prefix[1]))).build();
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ Ipv4MatchBuilder ipv4MatchBuilder = (Ipv4MatchBuilder) mapMatchBuilder.remove(Ipv4MatchBuilder.class);
+
+ if (ipv4MatchBuilder != null) {
+ matchBuilderInOut.setLayer3Match(ipv4MatchBuilder.build());
+ }
+ }
+ },
+
+ ipv4_destination {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return Ipv4Dst.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ Ipv4MatchBuilder ipv4MatchBuilder = (Ipv4MatchBuilder) mapMatchBuilder.get(Ipv4MatchBuilder.class);
+
+ if (ipv4MatchBuilder == null) {
+ ipv4MatchBuilder = new Ipv4MatchBuilder();
+ mapMatchBuilder.put(Ipv4MatchBuilder.class, ipv4MatchBuilder);
+ }
+
+ String[] prefix = matchInfo.getStringMatchValues();
+ ipv4MatchBuilder.setIpv4Destination(new Ipv4Prefix(prefix[0] + "/" + prefix[1])).build();
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ Ipv4MatchBuilder ipv4MatchBuilder = (Ipv4MatchBuilder) mapMatchBuilder.remove(Ipv4MatchBuilder.class);
+
+ if (ipv4MatchBuilder != null) {
+ matchBuilderInOut.setLayer3Match(ipv4MatchBuilder.build());
+ }
+ }
+ },
+
+ ipv4_source {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return Ipv4Src.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ Ipv4MatchBuilder ipv4MatchBuilder = (Ipv4MatchBuilder) mapMatchBuilder.get(Ipv4MatchBuilder.class);
+
+ if (ipv4MatchBuilder == null) {
+ ipv4MatchBuilder = new Ipv4MatchBuilder();
+ mapMatchBuilder.put(Ipv4MatchBuilder.class, ipv4MatchBuilder);
+ }
+
+ String[] prefix = matchInfo.getStringMatchValues();
+ ipv4MatchBuilder.setIpv4Source(new Ipv4Prefix(prefix[0] + "/" + prefix[1])).build();
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ Ipv4MatchBuilder ipv4MatchBuilder = (Ipv4MatchBuilder) mapMatchBuilder.remove(Ipv4MatchBuilder.class);
+
+ if (ipv4MatchBuilder != null) {
+ matchBuilderInOut.setLayer3Match(ipv4MatchBuilder.build());
+ }
+ }
+ },
+
+ arp_op {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return ArpOp.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ ArpMatchBuilder arpMatchBuilder = (ArpMatchBuilder) mapMatchBuilder.get(ArpMatchBuilder.class);
+
+ if (arpMatchBuilder == null) {
+ arpMatchBuilder = new ArpMatchBuilder();
+ mapMatchBuilder.put(ArpMatchBuilder.class, arpMatchBuilder);
+ }
+
+ arpMatchBuilder.setArpOp(Integer.valueOf((int) matchInfo.getMatchValues()[0]));
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ ArpMatchBuilder arpMatchBuilder = (ArpMatchBuilder) mapMatchBuilder.remove(ArpMatchBuilder.class);
+
+ if (arpMatchBuilder != null) {
+ matchBuilderInOut.setLayer3Match(arpMatchBuilder.build());
+ }
+ }
+ },
+
+ arp_tpa {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return ArpTpa.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ ArpMatchBuilder arpMatchBuilder = (ArpMatchBuilder) mapMatchBuilder.get(ArpMatchBuilder.class);
+
+ if (arpMatchBuilder == null) {
+ arpMatchBuilder = new ArpMatchBuilder();
+ mapMatchBuilder.put(ArpMatchBuilder.class, arpMatchBuilder);
+ }
+
+ long[] prefix = matchInfo.getMatchValues();
+ arpMatchBuilder.setArpTargetTransportAddress(new Ipv4Prefix(MDSALUtil.longToIp(prefix[0], prefix[1])));
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ ArpMatchBuilder arpMatchBuilder = (ArpMatchBuilder) mapMatchBuilder.remove(ArpMatchBuilder.class);
+
+ if (arpMatchBuilder != null) {
+ matchBuilderInOut.setLayer3Match(arpMatchBuilder.build());
+ }
+ }
+ },
+
+ arp_spa {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return ArpSpa.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ ArpMatchBuilder arpMatchBuilder = (ArpMatchBuilder) mapMatchBuilder.get(ArpMatchBuilder.class);
+
+ if (arpMatchBuilder == null) {
+ arpMatchBuilder = new ArpMatchBuilder();
+ mapMatchBuilder.put(ArpMatchBuilder.class, arpMatchBuilder);
+ }
+
+ long[] prefix = matchInfo.getMatchValues();
+ arpMatchBuilder.setArpSourceTransportAddress(new Ipv4Prefix(MDSALUtil.longToIp(prefix[0], prefix[1])));
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ ArpMatchBuilder arpMatchBuilder = (ArpMatchBuilder) mapMatchBuilder.remove(ArpMatchBuilder.class);
+
+ if (arpMatchBuilder != null) {
+ matchBuilderInOut.setLayer3Match(arpMatchBuilder.build());
+ }
+ }
+ },
+
+ metadata {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return Metadata.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ MetadataBuilder metadataBuilder = (MetadataBuilder) mapMatchBuilder.get(MetadataBuilder.class);
+
+ if (metadataBuilder == null) {
+ metadataBuilder = new MetadataBuilder();
+ mapMatchBuilder.put(MetadataBuilder.class, metadataBuilder);
+ }
+
+ BigInteger[] metadataValues = matchInfo.getBigMatchValues();
+ metadataBuilder.setMetadata(metadataValues[0]).setMetadataMask(metadataValues[1]).build();
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ MetadataBuilder metadataBuilder = (MetadataBuilder) mapMatchBuilder.remove(MetadataBuilder.class);
+
+ if (metadataBuilder != null) {
+ matchBuilderInOut.setMetadata(metadataBuilder.build());
+ }
+ }
+ },
+
+ mpls_label {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return MplsLabel.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ ProtocolMatchFieldsBuilder protocolMatchFieldsBuilder = (ProtocolMatchFieldsBuilder) mapMatchBuilder
+ .get(ProtocolMatchFieldsBuilder.class);
+
+ if (protocolMatchFieldsBuilder == null) {
+ protocolMatchFieldsBuilder = new ProtocolMatchFieldsBuilder();
+ mapMatchBuilder.put(ProtocolMatchFieldsBuilder.class, protocolMatchFieldsBuilder);
+ }
+
+ protocolMatchFieldsBuilder.setMplsLabel(Long.valueOf(matchInfo.getStringMatchValues()[0])).build();
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ ProtocolMatchFieldsBuilder protocolMatchFieldsBuilder = (ProtocolMatchFieldsBuilder) mapMatchBuilder
+ .remove(ProtocolMatchFieldsBuilder.class);
+
+ if (protocolMatchFieldsBuilder != null) {
+ matchBuilderInOut.setProtocolMatchFields(protocolMatchFieldsBuilder.build());
+ }
+ }
+ },
+
+ pbb_isid {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return PbbIsid.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ ProtocolMatchFieldsBuilder protocolMatchFieldsBuilder = (ProtocolMatchFieldsBuilder) mapMatchBuilder
+ .get(ProtocolMatchFieldsBuilder.class);
+
+ if (protocolMatchFieldsBuilder == null) {
+ protocolMatchFieldsBuilder = new ProtocolMatchFieldsBuilder();
+ mapMatchBuilder.put(ProtocolMatchFieldsBuilder.class, protocolMatchFieldsBuilder);
+ }
+
+ protocolMatchFieldsBuilder.setPbb(new PbbBuilder().setPbbIsid(Long.valueOf(matchInfo.getMatchValues()[0]))
+ .build());
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ ProtocolMatchFieldsBuilder protocolMatchFieldsBuilder = (ProtocolMatchFieldsBuilder) mapMatchBuilder
+ .remove(ProtocolMatchFieldsBuilder.class);
+
+ if (protocolMatchFieldsBuilder != null) {
+ matchBuilderInOut.setProtocolMatchFields(protocolMatchFieldsBuilder.build());
+ }
+ }
+ },
+
+ tcp_dst {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return TcpDst.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ TcpMatchBuilder tcpMatchBuilder = (TcpMatchBuilder) mapMatchBuilder.get(TcpMatchBuilder.class);
+
+ if (tcpMatchBuilder == null) {
+ tcpMatchBuilder = new TcpMatchBuilder();
+ mapMatchBuilder.put(TcpMatchBuilder.class, tcpMatchBuilder);
+ }
+
+ tcpMatchBuilder.setTcpDestinationPort(new PortNumber(Integer.valueOf((int) matchInfo.getMatchValues()[0])));
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ TcpMatchBuilder tcpMatchBuilder = (TcpMatchBuilder) mapMatchBuilder.remove(TcpMatchBuilder.class);
+
+ if (tcpMatchBuilder != null) {
+ matchBuilderInOut.setLayer4Match(tcpMatchBuilder.build());
+ }
+ }
+ },
+
+ tcp_src {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return TcpSrc.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ TcpMatchBuilder tcpMatchBuilder = (TcpMatchBuilder) mapMatchBuilder.get(TcpMatchBuilder.class);
+
+ if (tcpMatchBuilder == null) {
+ tcpMatchBuilder = new TcpMatchBuilder();
+ mapMatchBuilder.put(TcpMatchBuilder.class, tcpMatchBuilder);
+ }
+
+ tcpMatchBuilder.setTcpSourcePort(new PortNumber(Integer.valueOf((int) matchInfo.getMatchValues()[0])));
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ TcpMatchBuilder tcpMatchBuilder = (TcpMatchBuilder) mapMatchBuilder.remove(TcpMatchBuilder.class);
+
+ if (tcpMatchBuilder != null) {
+ matchBuilderInOut.setLayer4Match(tcpMatchBuilder.build());
+ }
+ }
+ },
+
+ udp_dst {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return UdpDst.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ UdpMatchBuilder udpMatchBuilder = (UdpMatchBuilder) mapMatchBuilder.get(UdpMatchBuilder.class);
+
+ if (udpMatchBuilder == null) {
+ udpMatchBuilder = new UdpMatchBuilder();
+ mapMatchBuilder.put(UdpMatchBuilder.class, udpMatchBuilder);
+ }
+
+ udpMatchBuilder.setUdpDestinationPort(new PortNumber(Integer.valueOf((int) matchInfo.getMatchValues()[0])));
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ UdpMatchBuilder udpMatchBuilder = (UdpMatchBuilder) mapMatchBuilder.remove(UdpMatchBuilder.class);
+
+ if (udpMatchBuilder != null) {
+ matchBuilderInOut.setLayer4Match(udpMatchBuilder.build());
+ }
+ }
+ },
+
+ udp_src {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return UdpSrc.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ UdpMatchBuilder udpMatchBuilder = (UdpMatchBuilder) mapMatchBuilder.get(UdpMatchBuilder.class);
+
+ if (udpMatchBuilder == null) {
+ udpMatchBuilder = new UdpMatchBuilder();
+ mapMatchBuilder.put(UdpMatchBuilder.class, udpMatchBuilder);
+ }
+
+ udpMatchBuilder.setUdpSourcePort(new PortNumber(Integer.valueOf((int) matchInfo.getMatchValues()[0])));
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ UdpMatchBuilder udpMatchBuilder = (UdpMatchBuilder) mapMatchBuilder.remove(UdpMatchBuilder.class);
+
+ if (udpMatchBuilder != null) {
+ matchBuilderInOut.setLayer4Match(udpMatchBuilder.build());
+ }
+ }
+ },
+ tunnel_id {
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ TunnelBuilder tunnelBuilder = (TunnelBuilder) mapMatchBuilder.get(TunnelBuilder.class);
+
+ if (tunnelBuilder == null) {
+ tunnelBuilder = new TunnelBuilder();
+ mapMatchBuilder.put(TunnelBuilder.class, tunnelBuilder);
+ }
+
+ BigInteger[] tunnelIdValues = matchInfo.getBigMatchValues();
+ tunnelBuilder.setTunnelId(tunnelIdValues[0]);
+ if(tunnelIdValues.length > 1){
+ tunnelBuilder.setTunnelMask(tunnelIdValues[1]);
+ }
+ tunnelBuilder.build();
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ TunnelBuilder tunnelBuilder = (TunnelBuilder) mapMatchBuilder.remove(TunnelBuilder.class);
+
+ if (tunnelBuilder != null) {
+ matchBuilderInOut.setTunnel(tunnelBuilder.build());
+ }
+ }
+
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return TunnelId.class;
+ }
+
+ },
+
+ vlan_vid {
+ @Override
+ protected Class<? extends MatchField> getMatchType() {
+ return VlanVid.class;
+ }
+
+ @Override
+ public void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ VlanMatchBuilder vlanMatchBuilder = (VlanMatchBuilder) mapMatchBuilder.get(VlanMatchBuilder.class);
+
+ if (vlanMatchBuilder == null) {
+ vlanMatchBuilder = new VlanMatchBuilder();
+ mapMatchBuilder.put(VlanMatchBuilder.class, vlanMatchBuilder);
+ }
+
+ vlanMatchBuilder.setVlanId(new VlanIdBuilder()
+ .setVlanId(new VlanId(Integer.valueOf((int) matchInfo.getMatchValues()[0])))
+ .setVlanIdPresent(((int) matchInfo.getMatchValues()[0] == 0) ? Boolean.FALSE : Boolean.TRUE)
+ .build());
+ }
+
+ @Override
+ public void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder) {
+ VlanMatchBuilder vlanMatchBuilder = (VlanMatchBuilder) mapMatchBuilder.remove(VlanMatchBuilder.class);
+
+ if (vlanMatchBuilder != null) {
+ matchBuilderInOut.setVlanMatch(vlanMatchBuilder.build());
+ }
+ }
+ };
+
+
+ public abstract void createInnerMatchBuilder(MatchInfo matchInfo, Map<Class<?>, Object> mapMatchBuilder);
+
+ public abstract void setMatch(MatchBuilder matchBuilderInOut, MatchInfo matchInfo,
+ Map<Class<?>, Object> mapMatchBuilder);
+
+ protected abstract Class<? extends MatchField> getMatchType();
+
+ protected boolean hasMatchFieldMask() {
+ // Override this to return true
+ return false;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.io.Serializable;
+import java.math.BigInteger;
+import java.util.Map;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+
+public class MatchInfo implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private final MatchFieldType m_matchField;
+ private long[] m_alMatchValues;
+ private BigInteger[] m_aBigIntValues;
+ private String[] m_asMatchValues;
+
+ public MatchInfo(MatchFieldType matchField, long[] alMatchValues) {
+ m_matchField = matchField;
+ m_alMatchValues = alMatchValues;
+ }
+
+ public MatchInfo(MatchFieldType matchField, BigInteger[] alBigMatchValues) {
+ m_matchField = matchField;
+ m_aBigIntValues = alBigMatchValues;
+ }
+
+ public MatchInfo(MatchFieldType matchField, String[] alStringMatchValues) {
+ m_matchField = matchField;
+ m_asMatchValues = alStringMatchValues;
+ }
+
+ public void createInnerMatchBuilder(Map<Class<?>, Object> mapMatchBuilder) {
+ m_matchField.createInnerMatchBuilder(this, mapMatchBuilder);
+ }
+
+ public void setMatch(MatchBuilder matchBuilder, Map<Class<?>, Object> mapMatchBuilder) {
+ m_matchField.setMatch(matchBuilder, this, mapMatchBuilder);
+ }
+
+ public MatchFieldType getMatchField() {
+ return m_matchField;
+ }
+
+ public long[] getMatchValues() {
+ return m_alMatchValues;
+ }
+
+ public BigInteger[] getBigMatchValues() {
+ return m_aBigIntValues;
+ }
+
+ public String[] getStringMatchValues() {
+ return m_asMatchValues;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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;
+
+
+public class MetaDataConstants {
+ // Nothing
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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 class MetaDataUtil {
+ public static final BigInteger METADATA_MASK_VRFID = new BigInteger("00000000FFFFFFFF", 16);
+ public static final BigInteger METADATA_MASK_LPORT_TAG = new BigInteger("1FFFFF0000000000", 16);
+ public static final BigInteger METADATA_MASK_SERVICE = new BigInteger("000000FFFF000000", 16);
+ public static final BigInteger METADATA_MASK_SERVICE_INDEX = new BigInteger("E000000000000000", 16);
+ public static final BigInteger METADATA_MASK_LPORT_WRITE = new BigInteger("00FFFF0000000000", 16);
+ public static final BigInteger METADA_MASK_VALID_TUNNEL_ID_BIT_AND_TUNNEL_ID = new BigInteger("08000000FFFFFF00", 16);
+ public static final BigInteger METADATA_MASK_LABEL_ITM = new BigInteger("40FFFFFF000000FF", 16);
+ public static final BigInteger METADA_MASK_TUNNEL_ID = new BigInteger("00000000FFFFFF00", 16);
+ public static final BigInteger METADATA_MASK_SERVICE_SH_FLAG = new BigInteger("000000FFFF000001", 16);
+ public static final BigInteger METADATA_MASK_LPORT_TAG_SH_FLAG = new BigInteger("1FFFFF0000000001", 16);
+
+ public static BigInteger getMetaDataForLPortDispatcher(int lportTag, short serviceIndex) {
+ return getServiceIndexMetaData(serviceIndex).or(getLportTagMetaData(lportTag));
+ }
+
+ public static BigInteger getMetaDataForLPortDispatcher(int lportTag, short serviceIndex,
+ BigInteger serviceMetaData) {
+ return getServiceIndexMetaData(serviceIndex).or(getLportTagMetaData(lportTag)).or(serviceMetaData);
+ }
+
+ public static BigInteger getServiceIndexMetaData(int serviceIndex) {
+ return new BigInteger("7", 16).and(BigInteger.valueOf(serviceIndex)).shiftLeft(61);
+ }
+
+ public static BigInteger getLportTagMetaData(int lportTag) {
+ return new BigInteger("1FFFFF", 16).and(BigInteger.valueOf(lportTag)).shiftLeft(40);
+ }
+
+ public static BigInteger getMetaDataMaskForLPortDispatcher() {
+ return METADATA_MASK_SERVICE_INDEX.or(METADATA_MASK_LPORT_TAG);
+ }
+
+ public static BigInteger getMetadataLPort(int lPortTag) {
+ return (new BigInteger("FFFF", 16).and(BigInteger.valueOf(lPortTag))).shiftLeft(40);
+ }
+
+ public static BigInteger getLportFromMetadata(BigInteger metadata) {
+ return (metadata.and(METADATA_MASK_LPORT_TAG)).shiftRight(40);
+ }
+
+ public static int getElanTagFromMetadata(BigInteger metadata) {
+ return (((metadata.and(MetaDataUtil.METADATA_MASK_SERVICE)).
+ shiftRight(24))).intValue();
+ }
+
+ public static BigInteger getMetaDataMaskForLPortDispatcher(BigInteger metadataMaskForServiceIndex,
+ BigInteger metadataMaskForLPortTag, BigInteger metadataMaskForService) {
+ return metadataMaskForServiceIndex.or(metadataMaskForLPortTag).or(metadataMaskForService);
+ }
+
+ /**
+ * For the tunnel id with VNI and valid-vni-flag set, the most significant byte
+ * should have 08. So, shifting 08 to 7 bytes (56 bits) and the result is OR-ed with
+ * VNI being shifted to 1 byte.
+ */
+ public static BigInteger getTunnelIdWithValidVniBitAndVniSet(int vni) {
+ return BigInteger.valueOf(0X08).shiftLeft(56).or(BigInteger.valueOf(vni).shiftLeft(8));
+ }
+
+ public static long getNatRouterIdFromMetadata(BigInteger metadata){
+ return (metadata.and(METADATA_MASK_VRFID)).longValue();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.net.InetAddress;
+
+import com.google.common.primitives.UnsignedBytes;
+
+public class NWUtil {
+
+ public static long convertInetAddressToLong(InetAddress address) {
+ byte[] ipAddressRaw = address.getAddress();
+ return (((ipAddressRaw[0] & 0xFF) << (3 * 8))
+ + ((ipAddressRaw[1] & 0xFF) << (2 * 8))
+ + ((ipAddressRaw[2] & 0xFF) << (1 * 8))
+ + (ipAddressRaw[3] & 0xFF))
+ & 0xffffffffL;
+ }
+
+ public static byte[] parseIpAddress(String ipAddress) {
+ byte cur;
+
+ String[] addressPart = ipAddress.split(".");
+ int size = addressPart.length;
+
+ byte[] part = new byte[size];
+ for (int i = 0; i < size; i++) {
+ cur = UnsignedBytes.parseUnsignedByte(addressPart[i], 16);
+ part[i] = cur;
+ }
+
+ return part;
+ }
+
+ public static byte[] parseMacAddress(String macAddress) {
+ byte cur;
+
+ String[] addressPart = macAddress.split(":");
+ int size = addressPart.length;
+
+ byte[] part = new byte[size];
+ for (int i = 0; i < size; i++) {
+ cur = UnsignedBytes.parseUnsignedByte(addressPart[i], 16);
+ part[i] = cur;
+ }
+
+ return part;
+ }
+
+ public static String toStringIpAddress(byte[] ipAddress)
+ {
+ if (ipAddress == null) {
+ return "";
+ }
+
+ StringBuilder sb = new StringBuilder(18);
+
+ for (int i = 0; i < ipAddress.length; i++) {
+ sb.append(UnsignedBytes.toString(ipAddress[i], 10));
+ sb.append(".");
+ }
+
+ sb.setLength(17);
+ return sb.toString();
+ }
+
+ public static String toStringMacAddress(byte[] macAddress)
+ {
+ if (macAddress == null) {
+ return "";
+ }
+
+ StringBuilder sb = new StringBuilder(18);
+
+ for (int i = 0; i < macAddress.length; i++) {
+ String tmp = UnsignedBytes.toString(macAddress[i], 16).toUpperCase();
+ if(tmp.length() == 1 || macAddress[i] == (byte)0) {
+ sb.append("0");
+ }
+ sb.append(tmp);
+ sb.append(":");
+ }
+
+ sb.setLength(17);
+ return sb.toString();
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.mdsalutil;
+
+public class NwConstants {
+
+ // EthType Values
+ public static final int ETHTYPE_802_1Q = 0X8100;
+ public static final int ETHTYPE_IPV4 = 0X0800;
+ public static final int ETHTYPE_ARP = 0X0806;
+
+ public static final int ETHTYPE_MPLS_UC = 0X8847;
+ public static final int ETHTYPE_PBB = 0X88E7;
+
+ //Protocol Type
+ public static final int IP_PROT_UDP = 17;
+ public static final int IP_PROT_GRE = 47;
+
+ //ARP TYPE
+ public static final int ARP_REQUEST = 1;
+ public static final int ARP_REPLY = 2;
+
+ //Default Port
+ public static final int UDP_DEFAULT_PORT = 4789;
+
+
+ // Flow Actions
+ public static final int ADD_FLOW = 0;
+ public static final int DEL_FLOW = 1;
+ public static final int MOD_FLOW = 2;
+
+ // Flow Constants
+ public static final String FLOWID_SEPARATOR = ".";
+ public static final int TABLE_MISS_FLOW = 0;
+ public static final int TABLE_MISS_PRIORITY = 0;
+
+ public static final int DEFAULT_ARP_FLOW_PRIORITY = 100;
+
+ //Table IDs
+ public static final short L3_FIB_TABLE = 21;
+ public static final short L3_LFIB_TABLE = 20;
+ public static final short L3_SUBNET_ROUTE_TABLE=22;
+
+ public static final short L3_PROTOCOL_TABLE = 36;
+ public static final short L3_INTERFACE_TABLE = 80;
+ public static final short LPORT_DISPATCHER_TABLE = 17;
+ public static final short VLAN_INTERFACE_INGRESS_TABLE = 0;
+ public static final short INTERNAL_TUNNEL_TABLE = 36;
+ public static final short EXTERNAL_TUNNEL_TABLE = 38;
+ public static final short DHCP_TABLE = 16;
+ public static final short DHCP_TABLE_EXTERNAL_TUNNEL = 18;
+ }
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.mdsalutil.interfaces;
+
+import java.math.BigInteger;
+import java.util.List;
+
+import com.google.common.util.concurrent.CheckedFuture;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
+import org.opendaylight.vpnservice.mdsalutil.GroupEntity;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+
+public interface IMdsalApiManager {
+
+ public void installFlow(FlowEntity flowEntity);
+
+ public CheckedFuture<Void,TransactionCommitFailedException> installFlow(BigInteger dpId, Flow flowEntity);
+
+ public CheckedFuture<Void,TransactionCommitFailedException> removeFlow(BigInteger dpId, Flow flowEntity);
+
+ public CheckedFuture<Void,TransactionCommitFailedException> removeFlow(BigInteger dpId, FlowEntity flowEntity);
+
+ public CheckedFuture<Void,TransactionCommitFailedException> installFlow(BigInteger dpId, FlowEntity flowEntity);
+
+ public void removeFlow(FlowEntity flowEntity);
+
+ public void installGroup(GroupEntity groupEntity);
+
+ public void modifyGroup(GroupEntity groupEntity);
+
+ public void removeGroup(GroupEntity groupEntity);
+
+ public void sendPacketOut(BigInteger dpnId, int groupId, byte[] payload);
+
+ public void sendPacketOutWithActions(BigInteger dpnId, long groupId, byte[] payload, List<ActionInfo> actionInfos);
+
+ 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);
+ public void syncInstallFlow(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);
+
+ public void syncInstallGroup(BigInteger dpId, Group group, 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);
+
+ public void syncRemoveGroup(BigInteger dpId, Group groupEntity);
+}
--- /dev/null
+/*
+ * Copyright (c) 2013, 2015 Cisco Systems, Inc. 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.packet;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.liblldp.BitBufferHelper;
+import org.opendaylight.controller.liblldp.Packet;
+
+/**
+ * Class that represents the ARP packet objects
+ * taken from opendaylight(helium) adsal bundle
+ *
+ */
+
+public class ARP extends Packet {
+ private static final String HWTYPE = "HardwareType";
+ private static final String PTYPE = "ProtocolType";
+ private static final String HWADDRLENGTH = "HardwareAddressLength";
+ private static final String PADDRLENGTH = "ProtocolAddressLength";
+ private static final String OPCODE = "OpCode";
+ private static final String SENDERHWADDR = "SenderHardwareAddress";
+ private static final String SENDERPADDR = "SenderProtocolAddress";
+ private static final String TARGETHWADDR = "TargetHardwareAddress";
+ private static final String TARGETPADDR = "TargetProtocolAddress";
+
+ public static short HW_TYPE_ETHERNET = (short) 0x1;
+ public static short REQUEST = (short) 0x1;
+ public static short REPLY = (short) 0x2;
+
+ public static short PROTO_TYPE_IP = 0x800;
+
+ private static Map<String, Pair<Integer, Integer>> fieldCoordinates = new LinkedHashMap<String, Pair<Integer, Integer>>() {
+ private static final long serialVersionUID = 1L;
+ {
+ put(HWTYPE, new ImmutablePair<Integer, Integer>(0, 16));
+ put(PTYPE, new ImmutablePair<Integer, Integer>(16, 16));
+ put(HWADDRLENGTH, new ImmutablePair<Integer, Integer>(32, 8));
+ put(PADDRLENGTH, new ImmutablePair<Integer, Integer>(40, 8));
+ put(OPCODE, new ImmutablePair<Integer, Integer>(48, 16));
+ put(SENDERHWADDR, new ImmutablePair<Integer, Integer>(64, 48));
+ put(SENDERPADDR, new ImmutablePair<Integer, Integer>(112, 32));
+ put(TARGETHWADDR, new ImmutablePair<Integer, Integer>(144, 48));
+ put(TARGETPADDR, new ImmutablePair<Integer, Integer>(192, 32));
+
+ }
+ };
+ private Map<String, byte[]> fieldValues;
+
+ /**
+ * Default constructor that creates and sets the HashMap
+ */
+ public ARP() {
+ super();
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ }
+
+ public ARP(boolean writeAccess) {
+ super(writeAccess);
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ }
+
+ public short getHardwareType() {
+ return (BitBufferHelper.getShort(fieldValues.get(HWTYPE)));
+
+ }
+
+ public short getProtocolType() {
+ return (BitBufferHelper.getShort(fieldValues.get(PTYPE)));
+ }
+
+ public byte getHardwareAddressLength() {
+ return (BitBufferHelper.getByte(fieldValues.get(HWADDRLENGTH)));
+ }
+
+ public byte getProtocolAddressLength() {
+ return (BitBufferHelper.getByte(fieldValues.get(PADDRLENGTH)));
+ }
+
+ public short getOpCode() {
+ return (BitBufferHelper.getShort(fieldValues.get(OPCODE)));
+ }
+
+ public byte[] getSenderHardwareAddress() {
+ return (fieldValues.get(SENDERHWADDR));
+ }
+
+ public byte[] getSenderProtocolAddress() {
+ return (fieldValues.get(SENDERPADDR));
+ }
+
+ public byte[] getTargetHardwareAddress() {
+ return (fieldValues.get(TARGETHWADDR));
+ }
+
+ public ARP setHardwareType(short hardwareType) {
+ byte[] hwType = BitBufferHelper.toByteArray(hardwareType);
+ fieldValues.put(HWTYPE, hwType);
+ return this;
+ }
+
+ public ARP setProtocolType(short protocolType) {
+ byte[] protType = BitBufferHelper.toByteArray(protocolType);
+ fieldValues.put(PTYPE, protType);
+ return this;
+ }
+
+ public ARP setHardwareAddressLength(byte hardwareAddressLength) {
+ byte[] hwAddressLength = BitBufferHelper
+ .toByteArray(hardwareAddressLength);
+ fieldValues.put(HWADDRLENGTH, hwAddressLength);
+ return this;
+ }
+
+ public ARP setProtocolAddressLength(byte protocolAddressLength) {
+ byte[] protocolAddrLength = BitBufferHelper
+ .toByteArray(protocolAddressLength);
+ fieldValues.put(PADDRLENGTH, protocolAddrLength);
+ return this;
+ }
+
+ public ARP setOpCode(short opCode) {
+ byte[] operationCode = BitBufferHelper.toByteArray(opCode);
+ fieldValues.put(OPCODE, operationCode);
+ return this;
+ }
+
+ public ARP setSenderHardwareAddress(byte[] senderHardwareAddress) {
+ fieldValues.put(SENDERHWADDR, senderHardwareAddress);
+ return this;
+ }
+
+ public ARP setTargetHardwareAddress(byte[] targetHardwareAddress) {
+ fieldValues.put(TARGETHWADDR, targetHardwareAddress);
+ return this;
+ }
+
+ public ARP setTargetProtocolAddress(byte[] targetProtocolAddress) {
+ fieldValues.put(TARGETPADDR, targetProtocolAddress);
+ return this;
+ }
+
+ public ARP setSenderProtocolAddress(byte[] senderIP) {
+ fieldValues.put(SENDERPADDR, senderIP);
+ return this;
+ }
+
+ public byte[] getTargetProtocolAddress() {
+ return fieldValues.get(TARGETPADDR);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result
+ + ((fieldValues == null) ? 0 : fieldValues.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ARP other = (ARP) obj;
+ if (fieldValues == null) {
+ if (other.fieldValues != null) {
+ return false;
+ }
+ } else if (!fieldValues.equals(other.fieldValues)) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013, 2015 Cisco Systems, Inc. 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.packet;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.liblldp.BitBufferHelper;
+import org.opendaylight.controller.liblldp.EtherTypes;
+import org.opendaylight.controller.liblldp.LLDP;
+import org.opendaylight.controller.liblldp.NetUtils;
+import org.opendaylight.controller.liblldp.Packet;
+
+/**
+ * Class that represents the Ethernet frame objects
+ * taken from opendaylight(helium) adsal bundle
+ */
+public class Ethernet extends Packet {
+ private static final String DMAC = "DestinationMACAddress";
+ private static final String SMAC = "SourceMACAddress";
+ private static final String ETHT = "EtherType";
+
+ // TODO: This has to be outside and it should be possible for osgi
+ // to add new coming packet classes
+ public static final Map<Short, Class<? extends Packet>> etherTypeClassMap;
+ static {
+ etherTypeClassMap = new HashMap<Short, Class<? extends Packet>>();
+ etherTypeClassMap.put(EtherTypes.ARP.shortValue(), ARP.class);
+ etherTypeClassMap.put(EtherTypes.LLDP.shortValue(), LLDP.class);
+ etherTypeClassMap.put(EtherTypes.IPv4.shortValue(), IPv4.class);
+ // TODO: Add support for more classes here
+ etherTypeClassMap.put(EtherTypes.VLANTAGGED.shortValue(), IEEE8021Q.class);
+ // etherTypeClassMap.put(EtherTypes.OLDQINQ.shortValue(), IEEE8021Q.class);
+ // etherTypeClassMap.put(EtherTypes.QINQ.shortValue(), IEEE8021Q.class);
+ // etherTypeClassMap.put(EtherTypes.CISCOQINQ.shortValue(), IEEE8021Q.class);
+ }
+ private static Map<String, Pair<Integer, Integer>> fieldCoordinates = new LinkedHashMap<String, Pair<Integer, Integer>>() {
+ private static final long serialVersionUID = 1L;
+ {
+ put(DMAC, new ImmutablePair<Integer, Integer>(0, 48));
+ put(SMAC, new ImmutablePair<Integer, Integer>(48, 48));
+ put(ETHT, new ImmutablePair<Integer, Integer>(96, 16));
+ }
+ };
+ private final Map<String, byte[]> fieldValues;
+
+ /**
+ * Default constructor that creates and sets the HashMap
+ */
+ public Ethernet() {
+ super();
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ }
+
+ /**
+ * Constructor that sets the access level for the packet and
+ * creates and sets the HashMap
+ * @param writeAccess boolean
+ */
+ public Ethernet(boolean writeAccess) {
+ super(writeAccess);
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ }
+
+ @Override
+ public void setHeaderField(String headerField, byte[] readValue) {
+ if (headerField.equals(ETHT)) {
+ payloadClass = etherTypeClassMap.get(BitBufferHelper
+ .getShort(readValue));
+ }
+ hdrFieldsMap.put(headerField, readValue);
+ }
+
+ public byte[] getDestinationMACAddress() {
+ return fieldValues.get(DMAC);
+ }
+
+ public byte[] getSourceMACAddress() {
+ return fieldValues.get(SMAC);
+ }
+
+ public short getEtherType() {
+ return BitBufferHelper.getShort(fieldValues.get(ETHT));
+ }
+
+ public boolean isBroadcast(){
+ return NetUtils.isBroadcastMACAddr(getDestinationMACAddress());
+ }
+
+ public boolean isMulticast(){
+ return NetUtils.isMulticastMACAddr(getDestinationMACAddress());
+ }
+
+ public Ethernet setDestinationMACAddress(byte[] destinationMACAddress) {
+ fieldValues.put(DMAC, destinationMACAddress);
+ return this;
+ }
+
+ public Ethernet setSourceMACAddress(byte[] sourceMACAddress) {
+ fieldValues.put(SMAC, sourceMACAddress);
+ return this;
+ }
+
+ public Ethernet setEtherType(short etherType) {
+ byte[] ethType = BitBufferHelper.toByteArray(etherType);
+ fieldValues.put(ETHT, ethType);
+ return this;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 - 2015 Cisco Systems, Inc. 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.packet;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.liblldp.BitBufferHelper;
+import org.opendaylight.controller.liblldp.BufferException;
+import org.opendaylight.controller.liblldp.NetUtils;
+import org.opendaylight.controller.liblldp.Packet;
+import org.opendaylight.controller.liblldp.PacketException;
+
+/**
+ * Class that represents the ICMP packet objects
+ */
+
+public class ICMP extends Packet {
+ private static final String TYPE = "Type";
+ private static final String CODE = "Code";
+ private static final String CHECKSUM = "Checksum";
+ private static final String IDENTIFIER = "Identifier";
+ private static final String SEQNUMBER = "SequenceNumber";
+
+ private static Map<String, Pair<Integer, Integer>> fieldCoordinates = new LinkedHashMap<String, Pair<Integer, Integer>>() {
+ private static final long serialVersionUID = 1L;
+ {
+ put(TYPE, new ImmutablePair<Integer, Integer>(0, 8));
+ put(CODE, new ImmutablePair<Integer, Integer>(8, 8));
+ put(CHECKSUM, new ImmutablePair<Integer, Integer>(16, 16));
+ put(IDENTIFIER, new ImmutablePair<Integer, Integer>(32, 16));
+ put(SEQNUMBER, new ImmutablePair<Integer, Integer>(48, 16));
+ }
+ };
+
+ /**
+ * Default constructor that creates and sets the hash map values
+ */
+ public ICMP() {
+ super();
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ }
+
+ /**
+ * Constructor that sets the access level for the packet
+ * @param writeAccess - boolean
+ */
+ public ICMP(boolean writeAccess) {
+ super(writeAccess);
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ }
+
+ private final Map<String, byte[]> fieldValues;
+
+ @Override
+ public void setHeaderField(String headerField, byte[] readValue) {
+ hdrFieldsMap.put(headerField, readValue);
+ }
+
+ /**
+ * Sets the type for the current ICMP message
+ *
+ * @param type
+ * The ICMP message type
+ * @return This ICMP object
+ */
+ public ICMP setType(byte type) {
+ byte[] icmpType = BitBufferHelper.toByteArray(type);
+ fieldValues.put(TYPE, icmpType);
+ return this;
+ }
+
+ /**
+ * Returns the type field of the current ICMP packet
+ *
+ * @return The type code of the current ICMP packet
+ */
+ public byte getType() {
+ return BitBufferHelper.getByte(fieldValues.get(TYPE));
+ }
+
+ /**
+ * Sets the ICMP code (type subtype) for the current ICMP object instance
+ *
+ * @param code
+ * The ICMP message type subtype
+ * @return This ICMP object
+ */
+ public ICMP setCode(byte code) {
+ byte[] icmpCode = BitBufferHelper.toByteArray(code);
+ fieldValues.put(CODE, icmpCode);
+ return this;
+ }
+
+ /**
+ * Gets the ICMP code (type subtype) for the current ICMP object instance
+ *
+ * @return The ICMP message type subtype
+ */
+ public byte getCode() {
+ return BitBufferHelper.getByte(fieldValues.get(CODE));
+ }
+
+ /**
+ * Sets the ICMP checksum for the current ICMP object instance
+ * @param checksum - short
+ * @return ICMP
+ */
+ public ICMP setChecksum(short checksum) {
+ byte[] icmpChecksum = BitBufferHelper.toByteArray(checksum);
+ fieldValues.put(CHECKSUM, icmpChecksum);
+ return this;
+ }
+
+ /**
+ * Sets the ICMP identifier for the current ICMP object instance
+ * @param identifier - short
+ * @return ICMP
+ */
+ public ICMP setIdentifier(short identifier) {
+ byte[] icmpIdentifier = BitBufferHelper.toByteArray(identifier);
+ fieldValues.put(IDENTIFIER, icmpIdentifier);
+ return this;
+ }
+
+ /**
+ * Gets the ICMP identifier of the current ICMP object instance
+ *
+ * @return short - identifier
+ */
+
+ public short getIdentifier() {
+ return BitBufferHelper.getShort(fieldValues.get(IDENTIFIER));
+ }
+
+ /**
+ * Sets the ICMP sequence number for the current ICMP object instance
+ * @param seqNumber-short
+ * @return ICMP
+ */
+ public ICMP setSequenceNumber(short seqNumber) {
+ byte[] icmpSeqNumber = BitBufferHelper.toByteArray(seqNumber);
+ fieldValues.put(SEQNUMBER, icmpSeqNumber);
+ return this;
+ }
+
+ /**
+ * Gets the ICMP sequence number of the current ICMP object instance
+ *
+ * @return short - seqNumber
+ */
+
+ public short getSequenceNumber() {
+ return BitBufferHelper.getShort(fieldValues.get(SEQNUMBER));
+ }
+
+ /**
+ * Gets the header size in bits
+ * @return The ICMP header size in bits
+ */
+ @Override
+ public int getHeaderSize() {
+ return 64;
+ }
+
+ /**
+ * Computes the ICMP checksum on the serialized ICMP message
+ *
+ * @param data
+ * The serialized data stream
+ * @param start
+ * The byte index on the data stream from which the ICMP packet
+ * starts
+ * @return The checksum
+ */
+ short computeChecksum(byte[] data, int start) {
+ int sum = 0, carry = 0, finalSum = 0;
+ int wordData;
+ int end = start + this.getHeaderSize() / NetUtils.NumBitsInAByte;
+ if (rawPayload != null) {
+ end += rawPayload.length;
+ }
+ int checksumStartByte = start + getfieldOffset(CHECKSUM) / NetUtils.NumBitsInAByte;
+ int even = end & ~1;
+
+ for (int i = start; i < even; i = i + 2) {
+ // Skip, if the current bytes are checkSum bytes
+ if (i == checksumStartByte) {
+ continue;
+ }
+ wordData = ((data[i] << 8) & 0xFF00) + (data[i + 1] & 0xFF);
+ sum = sum + wordData;
+ }
+ if (even < end) {
+ // Add the last octet with zero padding.
+ wordData = (data[even] << 8) & 0xFF00;
+ sum = sum + wordData;
+ }
+
+ carry = sum >>> 16;
+ finalSum = (sum & 0xFFFF) + carry;
+ return (short) ~((short) finalSum & 0xFFFF);
+ }
+
+ @Override
+ protected void postSerializeCustomOperation(byte[] serializedBytes)
+ throws PacketException {
+ byte[] checkSum = BitBufferHelper
+ .toByteArray(computeChecksum(serializedBytes, 0));
+ try {
+ BitBufferHelper.setBytes(serializedBytes, checkSum,
+ getfieldOffset(CHECKSUM), getfieldnumBits(CHECKSUM));
+ } catch (BufferException e) {
+ throw new PacketException(e.getMessage());
+ }
+ }
+
+ @Override
+ protected void postDeserializeCustomOperation(byte[] data, int endBitOffset) {
+ short computedChecksum = computeChecksum(data, endBitOffset / NetUtils.NumBitsInAByte);
+ short actualChecksum = BitBufferHelper.getShort(fieldValues.get(CHECKSUM));
+
+ if (computedChecksum != actualChecksum) {
+ corrupted = true;
+ }
+ }
+
+ /**
+ * Gets the checksum value stored
+ * @return the checksum
+ */
+ public short getChecksum() {
+ return (BitBufferHelper.getShort(fieldValues.get(CHECKSUM)));
+ }
+}
--- /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.packet;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.liblldp.BitBufferHelper;
+
+public class IEEE8021Q extends Ethernet {
+ private static final String PRIORITY = "Priority";
+ private static final String CFI = "CFI";
+ private static final String VLAN_ID = "VlanId";
+ private static final String ETHT = "EtherType";
+
+ private static Map<String, Pair<Integer, Integer>> fieldCoordinates = new LinkedHashMap<String, Pair<Integer, Integer>>() {
+ private static final long serialVersionUID = 1L;
+ {
+ put(PRIORITY, new ImmutablePair<Integer, Integer>(0, 3));
+ put(CFI, new ImmutablePair<Integer, Integer>(3, 1));
+ put(VLAN_ID, new ImmutablePair<Integer, Integer>(4, 12));
+ put(ETHT, new ImmutablePair<Integer, Integer>(16, 16));
+ }
+ };
+ private Map<String, byte[]> fieldValues;
+
+ /**
+ * Default constructor that creates and sets the HashMap
+ */
+ public IEEE8021Q() {
+ super();
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ }
+
+ public IEEE8021Q(boolean writeAccess) {
+ super(writeAccess);
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ }
+
+ public short getPriority() {
+ return (BitBufferHelper.getShort(fieldValues.get(PRIORITY)));
+ }
+
+ public short getCfi() {
+ return (BitBufferHelper.getShort(fieldValues.get(CFI)));
+ }
+
+ public short getVlanId() {
+ return (BitBufferHelper.getShort(fieldValues.get(VLAN_ID)));
+ }
+
+ @Override
+ public short getEtherType() {
+ return BitBufferHelper.getShort(fieldValues.get(ETHT));
+ }
+
+ public IEEE8021Q setPriority(short priority) {
+ byte[] priorityByte = BitBufferHelper.toByteArray(priority);
+ fieldValues.put(PRIORITY, priorityByte);
+ return this;
+ }
+
+ public IEEE8021Q setCFI(short cfi) {
+ byte[] cfiByte = BitBufferHelper
+ .toByteArray(cfi);
+ fieldValues.put(CFI, cfiByte);
+ return this;
+ }
+
+ public IEEE8021Q setVlanId(short vlanId) {
+ byte[] vlan = BitBufferHelper
+ .toByteArray(vlanId);
+ fieldValues.put(VLAN_ID, vlan);
+ return this;
+ }
+
+ @Override
+ public IEEE8021Q setEtherType(short etherType) {
+ byte[] ethType = BitBufferHelper.toByteArray(etherType);
+ fieldValues.put(ETHT, ethType);
+ return this;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result
+ + ((fieldValues == null) ? 0 : fieldValues.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ IEEE8021Q other = (IEEE8021Q) obj;
+ if (fieldValues == null) {
+ if (other.fieldValues != null) {
+ return false;
+ }
+ } else if (!fieldValues.equals(other.fieldValues)) {
+ return false;
+ }
+ return true;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013, 2015 Cisco Systems, Inc. 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.packet;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Enum represents the most common IP protocols numbers It provides the binding
+ * between IP protocol names and numbers and provides APIs to read and parse
+ * them in either of the two forms
+ *
+ * NOTE: Openflow 1.0 supports the IP Proto match only for ICMP, TCP and UDP
+ *
+ * references:
+ * http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
+ */
+public enum IPProtocols {
+ ANY("any", -1),
+ HOPOPT("HOPOPT",0),
+ ICMP("ICMP", 1),
+ IGMP("IGMP",2),
+ GGP("GGP",3),
+ IPV4("IPv4",4),
+ ST("ST",5),
+ TCP("TCP", 6),
+ CBT("CBT",7),
+ EGP("EGP",8),
+ IGP("IGP",9),
+ BBNRCCMON("BBN-RCC-MON",10),
+ NVPII("NVP-II",11),
+ PUP("PUP",12),
+ ARGUS("ARGUS",13),
+ EMCON("EMCON",14),
+ XNET("XNET",15),
+ CHAOS("CHAOS",16),
+ UDP("UDP", 17),
+ MUX("MUX",18),
+ DCNMEAS("DCN-MEAS",19),
+ HMP("HMP",20),
+ PRM("PRM",21),
+ XNSIDP("XNS-IDP",22),
+ TRUNK1("TRUNK-1",23),
+ TRUNK2("TRUNK-2",24),
+ LEAF1("LEAF-1",25),
+ LEAF2("LEAF-2",26),
+ RDP("RDP",27),
+ IRTP("IRTP",28),
+ ISOTP4("ISO-TP4",29),
+ NETBLT("NETBLT",30),
+ MFENSP("MFE-NSP",31),
+ MERITINP("MERIT-INP",32),
+ DCCP("DCCP",33),
+ THREEPC("3PC",34),
+ IDPR("IDPR",35),
+ XTP("XTP",36),
+ DDP("DDP",37),
+ IDPRCMTP("IDPR-CMTP",38),
+ TPPLUSPLUS("TP++",39),
+ IL("IL",40),
+ IPV6("IPv6",41),
+ SDRP("SDRP",42),
+ IPV6Route("IPv6-Route",43),
+ IPV6Frag("IPv6-Frag",44),
+ IDRP("IDRP",45),
+ RSVP("RSVP",46),
+ GRE("GRE",47),
+ DSR("DSR",48),
+ BNA("BNA",49),
+ ESP("ESP",50),
+ AH("AH",51),
+ INLSP("I-NLSP",52),
+ SWIPE("SWIPE",53),
+ NARP("NARP",54),
+ MOBILE("MOBILE",55),
+ TLSP("TLSP",56),
+ SKIP("SKIP",57),
+ IPV6ICMP("IPv6-ICMP", 58),
+ IPV6NoNxt("IPv6-NoNxt",59),
+ IPV6Opts("IPv6-Opts",60),
+ ANYHOST("ANY-HOST",61),
+ CFTP("CFTP",62),
+ ANYNETWORK("ANY-NETWORK",63),
+ SATEXPAK("SAT-EXPAK",64),
+ KRYPTOLAN("KRYPTOLAN",65),
+ RVD("RVD",66),
+ IPPC("IPPC",67),
+ ANYDISTFS("ANY-DIST-FS",68),
+ SATMON("SAT-MON",69),
+ VISA("VISA",70),
+ IPCV("IPCV",71),
+ CPNX("CPNX",72),
+ CPHB("CPHB",73),
+ WSN("WSN",74),
+ PVP("PVP",75),
+ BRSATMON("BR-SAT-MON",76),
+ SUNND("SUN-ND",77),
+ WBMON("WB-MON",78),
+ WBEXPAK("WB-EXPAK",79),
+ ISOIP("ISO-IP",80),
+ VMTP("VMTP",81),
+ SECUREVMTP("SECURE-VMTP",82),
+ VINES("VINES",83),
+ TTP("TTP",84),
+ IPTM("IPTM",84),
+ NSFNETIGP("NSFNET-IGP",85),
+ DGP("DGP",86),
+ TCF("TCF",87),
+ EIGRP("EIGRP",88),
+ OSPFIGP("OSPFIGP",89),
+ SPRITERPC("Sprite-RPC",90),
+ LARP("LARP",91),
+ MTP("MTP",92),
+ AX25("AX.25",93),
+ IPIP("IPIP",94),
+ MICP("MICP",95),
+ SCCSP("SCC-SP",96),
+ ETHERIP("ETHERIP",97),
+ ENCAP("ENCAP",98),
+ ANYENC("ANY-ENC",99),
+ GMTP("GMTP",100),
+ IFMP("IFMP",101),
+ PNNI("PNNI",102),
+ PIM("PIM",103),
+ ARIS("ARIS",104),
+ SCPS("SCPS",105),
+ QNX("QNX",106),
+ AN("A/N",107),
+ IPComp("IPComp",108),
+ SNP("SNP",109),
+ COMPAQPEER("Compaq-Peer",110),
+ IPXINIP("IPX-in-IP",111),
+ VRRP("VRRP",112),
+ PGM("PGM",113),
+ ANY0HOP("ANY-0-HOP",114),
+ L2TP("L2TP",115),
+ DDX("DDX",116),
+ IATP("IATP",117),
+ STP("STP",118),
+ SRP("SRP",119),
+ UTI("UTI",120),
+ SMP("SMP",121),
+ SM("SM",122),
+ PTP("PTP",123),
+ ISIS("ISIS",124),
+ FIRE("FIRE",125),
+ CRTP("CRTP",126),
+ CRUDP("CRUDP",127),
+ SSCOPMCE("SSCOPMCE",128),
+ IPLT("IPLT",129),
+ SPS("SPS",130),
+ PIPE("PIPE",131),
+ SCTP("SCTP",132),
+ FC("FC",133),
+ RSVPE2EIGNORE("RSVP-E2E-IGNORE",134),
+ MOBILITYHEADER("Mobility Header",135),
+ UDPLITE("UDPLite",136),
+ MPLSINIP("MPLS-in-IP",137),
+ MANET("MANET",138),
+ HIP("HIP",139),
+ SHIM6("Shim6",140),
+ WESP("WESP",141),
+ ROHC("ROHC",142),
+ /*143-252 Unassigned by IANA*/
+
+ //Experimebtal protocol numbers (http://tools.ietf.org/html/rfc3692)
+ EXP1("Experimental1", 253),
+ EXP2("Experimental2", 254),
+
+ RESERVED("RESERVED",255);
+
+ private String protocolName;
+ private int protocolNumber;
+
+ private IPProtocols(String name, int number) {
+ protocolName = name;
+ protocolNumber = number;
+ }
+
+ public int intValue() {
+ return protocolNumber;
+ }
+
+ public short shortValue() {
+ return ((Integer) protocolNumber).shortValue();
+ }
+
+ public byte byteValue() {
+ return ((Integer) protocolNumber).byteValue();
+ }
+
+ @Override
+ public String toString() {
+ return protocolName;
+ }
+
+ public static String getProtocolName(int number) {
+ return getProtocolNameInternal(number);
+ }
+
+ public static String getProtocolName(short number) {
+ return getProtocolNameInternal(number & 0xffff);
+ }
+
+ public static String getProtocolName(byte number) {
+ return getProtocolNameInternal(number & 0xff);
+ }
+
+ private static String getProtocolNameInternal(int number) {
+ for (IPProtocols proto : IPProtocols.values()) {
+ if (proto.protocolNumber == number) {
+ return proto.toString();
+ }
+ }
+ //TODO: this is for backwards compatibility
+ return "0x" + Integer.toHexString(number);
+ }
+
+ public static short getProtocolNumberShort(String name) {
+ IPProtocols p = fromString(name);
+ if (p != null) {
+ return p.shortValue();
+ }
+ //This method should be called after validation only
+ throw new IllegalArgumentException("Illegal IP protocol value: " + name);
+ }
+
+ public static int getProtocolNumberInt(String name) {
+ IPProtocols p = fromString(name);
+ if (p != null) {
+ return p.intValue();
+ }
+ //This method should be called after validation only
+ throw new IllegalArgumentException("Illegal IP protocol value: " + name);
+ }
+
+ public static byte getProtocolNumberByte(String name) {
+ IPProtocols p = fromString(name);
+ if (p != null) {
+ return p.byteValue();
+ }
+ //This method should be called after validation only
+ throw new IllegalArgumentException("Illegal IP protocol value: " + name);
+ }
+
+ public static List<String> getProtocolNameList() {
+ List<String> protoList = new ArrayList<String>();
+ for (IPProtocols proto : IPProtocols.values()) {
+ protoList.add(proto.toString());
+ }
+ return protoList;
+ }
+
+ /**
+ * Method to parse an IPProtocol from a numeric string
+ *
+ * @param s
+ * The IP protocol string to be parsed
+ * @return The IP protocol Enum, or null if invalid protocol string is passed
+ */
+ public static IPProtocols fromString(String s) {
+ // null/empty/any/* evaluates to ANY
+ if (s == null || s.isEmpty() || s.equalsIgnoreCase("any") || s.equals("*")) {
+ return IPProtocols.ANY;
+ }
+
+ // Try parsing numeric and find the related ENUM
+ try {
+ int protoNum = Integer.decode(s);
+ for (IPProtocols protoEnum : IPProtocols.values()) {
+ if (protoEnum.protocolNumber == protoNum) {
+ return protoEnum;
+ }
+ }
+ // At this point it's an invalid number (i.e. out of range or not a valid proto num)
+ return null;
+ } catch (NumberFormatException nfe) {
+ // numeric failed try by NAME
+ try {
+ return valueOf(s);
+ } catch(IllegalArgumentException e) {
+ // Neither numeric nor enum NAME, attempt human readable name
+ for (IPProtocols protoEnum : IPProtocols.values()) {
+ if (protoEnum.toString().equalsIgnoreCase(s)) {
+ return protoEnum;
+ }
+ }
+ //couldn't parse, signifies an invalid proto field!
+ return null;
+ }
+
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 - 2015 Cisco Systems, Inc. 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.packet;
+
+import java.net.InetAddress;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Random;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.liblldp.BitBufferHelper;
+import org.opendaylight.controller.liblldp.BufferException;
+import org.opendaylight.controller.liblldp.NetUtils;
+import org.opendaylight.controller.liblldp.Packet;
+import org.opendaylight.controller.liblldp.PacketException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class that represents the IPv4 packet objects
+ */
+
+public class IPv4 extends Packet {
+ protected static final Logger logger = LoggerFactory
+ .getLogger(IPv4.class);
+ private static final String VERSION = "Version";
+ private static final String HEADERLENGTH = "HeaderLength";
+ private static final String DIFFSERV = "DiffServ";
+ private static final String ECN = "ECN";
+ private static final String TOTLENGTH = "TotalLength";
+ private static final String IDENTIFICATION = "Identification";
+ private static final String FLAGS = "Flags";
+ private static final String FRAGOFFSET = "FragmentOffset";
+ private static final String TTL = "TTL";
+ private static final String PROTOCOL = "Protocol";
+ private static final String CHECKSUM = "Checksum";
+ private static final String SIP = "SourceIPAddress";
+ private static final String DIP = "DestinationIPAddress";
+ private static final String OPTIONS = "Options";
+
+ private static final int UNIT_SIZE_SHIFT = 2;
+ private static final int UNIT_SIZE = (1 << UNIT_SIZE_SHIFT);
+ private static final int MIN_HEADER_SIZE = 20;
+
+ public static final Map<Byte, Class<? extends Packet>> protocolClassMap;
+ static {
+ protocolClassMap = new HashMap<Byte, Class<? extends Packet>>();
+ protocolClassMap.put(IPProtocols.ICMP.byteValue(), ICMP.class);
+ protocolClassMap.put(IPProtocols.UDP.byteValue(), UDP.class);
+ protocolClassMap.put(IPProtocols.TCP.byteValue(), TCP.class);
+ }
+ private static Map<String, Pair<Integer, Integer>> fieldCoordinates = new LinkedHashMap<String, Pair<Integer, Integer>>() {
+ private static final long serialVersionUID = 1L;
+ {
+ put(VERSION, new ImmutablePair<Integer, Integer>(0, 4));
+ put(HEADERLENGTH, new ImmutablePair<Integer, Integer>(4, 4));
+ put(DIFFSERV, new ImmutablePair<Integer, Integer>(8, 6));
+ put(ECN, new ImmutablePair<Integer, Integer>(14, 2));
+ put(TOTLENGTH, new ImmutablePair<Integer, Integer>(16, 16));
+ put(IDENTIFICATION, new ImmutablePair<Integer, Integer>(32, 16));
+ put(FLAGS, new ImmutablePair<Integer, Integer>(48, 3));
+ put(FRAGOFFSET, new ImmutablePair<Integer, Integer>(51, 13));
+ put(TTL, new ImmutablePair<Integer, Integer>(64, 8));
+ put(PROTOCOL, new ImmutablePair<Integer, Integer>(72, 8));
+ put(CHECKSUM, new ImmutablePair<Integer, Integer>(80, 16));
+ put(SIP, new ImmutablePair<Integer, Integer>(96, 32));
+ put(DIP, new ImmutablePair<Integer, Integer>(128, 32));
+ put(OPTIONS, new ImmutablePair<Integer, Integer>(160, 0));
+ }
+ };
+
+ private final Map<String, byte[]> fieldValues;
+
+
+ /**
+ * Default constructor that sets the version to 4, headerLength to 5,
+ * and flags to 2. The default value for the identification is set to a
+ * random number and the remaining fields are set to 0.
+ */
+ public IPv4() {
+ super();
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ corrupted = false;
+
+ setVersion((byte) 4);
+ setHeaderLength((byte) 5);
+ setDiffServ((byte) 0);
+ setECN((byte) 0);
+ setIdentification(generateId());
+ setFlags((byte) 2);
+ setFragmentOffset((short) 0);
+ }
+
+ /**
+ * The write access to the packet is set in this constructor.
+ * Constructor that sets the version to 4, headerLength to 5,
+ * and flags to 2. The default value for the identification is set to a
+ * random number and the remaining fields are set to 0.
+ * @param writeAccess - boolean
+ */
+ public IPv4(boolean writeAccess) {
+ super(writeAccess);
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ corrupted = false;
+
+ setVersion((byte) 4);
+ setHeaderLength((byte) 5);
+ setDiffServ((byte) 0);
+ setECN((byte) 0);
+ setIdentification(generateId());
+ setFlags((byte) 2);
+ setFragmentOffset((short) 0);
+ }
+
+ /**
+ * Gets the IP version stored
+ * @return the version
+ */
+ public byte getVersion() {
+ return (BitBufferHelper.getByte(fieldValues.get(VERSION)));
+ }
+
+ /**
+ * Gets the IP header length stored
+ * @return the headerLength in bytes
+ */
+ public int getHeaderLen() {
+ return (4 * BitBufferHelper.getByte(fieldValues.get(HEADERLENGTH)));
+ }
+
+ /**
+ * Gets the header size in bits
+ * @return The number of bits constituting the header
+ */
+ @Override
+ public int getHeaderSize() {
+ int headerLen = this.getHeaderLen();
+ if (headerLen == 0) {
+ headerLen = MIN_HEADER_SIZE;
+ }
+
+ return headerLen * NetUtils.NumBitsInAByte;
+ }
+
+ /**
+ * Gets the differential services value stored
+ * @return the diffServ
+ */
+ public byte getDiffServ() {
+ return BitBufferHelper.getByte(fieldValues.get(DIFFSERV));
+ }
+
+ /**
+ * Gets the ecn bits stored
+ * @return the ecn bits
+ */
+ public byte getECN() {
+ return BitBufferHelper.getByte(fieldValues.get(ECN));
+ }
+
+ /**
+ * Gets the total length of the IP header in bytes
+ * @return the totalLength
+ */
+ public short getTotalLength() {
+ return (BitBufferHelper.getShort(fieldValues.get(TOTLENGTH)));
+ }
+
+ /**
+ * Gets the identification value stored
+ * @return the identification
+ */
+ public short getIdentification() {
+ return (BitBufferHelper.getShort(fieldValues.get(IDENTIFICATION)));
+ }
+
+ /**
+ * Gets the flag values stored
+ * @return the flags
+ */
+ public byte getFlags() {
+ return (BitBufferHelper.getByte(fieldValues.get(FLAGS)));
+ }
+
+ /**
+ * Gets the TTL value stored
+ * @return the ttl
+ */
+ public byte getTtl() {
+ return (BitBufferHelper.getByte(fieldValues.get(TTL)));
+ }
+
+ /**
+ * Gets the protocol value stored
+ * @return the protocol
+ */
+ public byte getProtocol() {
+ return (BitBufferHelper.getByte(fieldValues.get(PROTOCOL)));
+ }
+
+ /**
+ * Gets the checksum value stored
+ * @return the checksum
+ */
+ public short getChecksum() {
+ return (BitBufferHelper.getShort(fieldValues.get(CHECKSUM)));
+ }
+
+ /**
+ * Gets the fragment offset stored
+ * @return the fragmentOffset
+ */
+ public short getFragmentOffset() {
+ return (BitBufferHelper.getShort(fieldValues.get(FRAGOFFSET)));
+ }
+
+ /**
+ * Gets the source IP address stored
+ * @return the sourceAddress
+ */
+ public int getSourceAddress() {
+ return (BitBufferHelper.getInt(fieldValues.get(SIP)));
+ }
+
+ /**
+ * Gets the destination IP address stored
+ * @return the destinationAddress
+ */
+ public int getDestinationAddress() {
+ return (BitBufferHelper.getInt(fieldValues.get(DIP)));
+ }
+
+ /**
+ * gets the Options stored
+ * @return the options
+ */
+ public byte[] getOptions() {
+ return (fieldValues.get(OPTIONS));
+ }
+
+ @Override
+ /**
+ * Stores the value of fields read from data stream
+ * Variable header value like payload protocol, is stored here
+ * @param headerField
+ * @param readValue
+ */
+ public void setHeaderField(String headerField, byte[] readValue) {
+ if (headerField.equals(PROTOCOL)) {
+ // Don't set payloadClass if framgment offset is not zero.
+ byte[] fragoff = hdrFieldsMap.get(FRAGOFFSET);
+ if (fragoff == null || BitBufferHelper.getShort(fragoff) == 0) {
+ payloadClass = protocolClassMap.get(readValue[0]);
+ }
+ } else if (headerField.equals(FRAGOFFSET)) {
+ if (readValue != null && BitBufferHelper.getShort(readValue) != 0) {
+ // Clear payloadClass because protocol header is not present
+ // in this packet.
+ payloadClass = null;
+ }
+ } else if (headerField.equals(OPTIONS) &&
+ (readValue == null || readValue.length == 0)) {
+ hdrFieldsMap.remove(headerField);
+ return;
+ }
+ hdrFieldsMap.put(headerField, readValue);
+ }
+
+ /**
+ * Stores the IP version from the header
+ * @param ipVersion the version to set
+ * @return IPv4
+ */
+ public IPv4 setVersion(byte ipVersion) {
+ byte[] version = BitBufferHelper.toByteArray(ipVersion);
+ fieldValues.put(VERSION, version);
+ return this;
+ }
+
+ /**
+ * Stores the length of IP header in words (4 bytes)
+ * @param ipheaderLength the headerLength to set
+ * @return IPv4
+ */
+ public IPv4 setHeaderLength(byte ipheaderLength) {
+ byte[] headerLength = BitBufferHelper.toByteArray(ipheaderLength);
+ fieldValues.put(HEADERLENGTH, headerLength);
+ return this;
+ }
+
+ /**
+ * Stores the differential services value from the IP header
+ * @param ipdiffServ the diffServ to set
+ * @return IPv4
+ */
+ public IPv4 setDiffServ(byte ipdiffServ) {
+ byte[] diffServ = BitBufferHelper.toByteArray(ipdiffServ);
+ fieldValues.put(DIFFSERV, diffServ);
+ return this;
+ }
+
+ /**
+ * Stores the ECN bits from the header
+ * @param ecn ECN bits to set
+ * @return IPv4
+ */
+ public IPv4 setECN(byte ecn) {
+ byte[] ecnbytes = BitBufferHelper.toByteArray(ecn);
+ fieldValues.put(ECN, ecnbytes);
+ return this;
+ }
+
+ /**
+ * Stores the total length of IP header in bytes
+ * @param iptotalLength the totalLength to set
+ * @return IPv4
+ */
+ public IPv4 setTotalLength(short iptotalLength) {
+ byte[] totalLength = BitBufferHelper.toByteArray(iptotalLength);
+ fieldValues.put(TOTLENGTH, totalLength);
+ return this;
+ }
+
+ /**
+ * Stores the identification number from the header
+ * @param ipIdentification the identification to set
+ * @return IPv4
+ */
+ public IPv4 setIdentification(short ipIdentification) {
+ byte[] identification = BitBufferHelper.toByteArray(ipIdentification);
+ fieldValues.put(IDENTIFICATION, identification);
+ return this;
+ }
+
+ /**
+ * Stores the IP flags value
+ * @param ipFlags the flags to set
+ * @return IPv4
+ */
+ public IPv4 setFlags(byte ipFlags) {
+ byte[] flags = { ipFlags };
+ fieldValues.put(FLAGS, flags);
+ return this;
+ }
+
+ /**
+ * Stores the IP fragmentation offset value
+ * @param ipFragmentOffset the fragmentOffset to set
+ * @return IPv4
+ */
+ public IPv4 setFragmentOffset(short ipFragmentOffset) {
+ byte[] fragmentOffset = BitBufferHelper.toByteArray(ipFragmentOffset);
+ fieldValues.put(FRAGOFFSET, fragmentOffset);
+ return this;
+ }
+
+ /**
+ * Stores the TTL value
+ * @param ipTtl the ttl to set
+ * @return IPv4
+ */
+ public IPv4 setTtl(byte ipTtl) {
+ byte[] ttl = BitBufferHelper.toByteArray(ipTtl);
+ fieldValues.put(TTL, ttl);
+ return this;
+ }
+
+ /**
+ * Stores the protocol value of the IP payload
+ * @param ipProtocol the protocol to set
+ * @return IPv4
+ */
+ public IPv4 setProtocol(byte ipProtocol) {
+ byte[] protocol = BitBufferHelper.toByteArray(ipProtocol);
+ fieldValues.put(PROTOCOL, protocol);
+ return this;
+ }
+
+ /**
+ * @param checksum the checksum to set
+ */
+ /*public IPv4 setChecksum() {
+ short ipChecksum = computeChecksum();
+ byte[] checksum = BitBufferHelper.toByteArray(ipChecksum);
+ fieldValues.put(CHECKSUM, checksum);
+ return this;
+ }*/
+
+ /**
+ * Stores the IP source address from the header
+ * @param ipSourceAddress the sourceAddress to set
+ * @return IPv4
+ */
+ public IPv4 setSourceAddress(InetAddress ipSourceAddress) {
+ byte[] sourceAddress = ipSourceAddress.getAddress();
+ fieldValues.put(SIP, sourceAddress);
+ return this;
+ }
+
+ /**
+ * Stores the IP destination address from the header
+ * @param ipDestinationAddress the destination Address to set
+ * @return IPv4
+ */
+ public IPv4 setDestinationAddress(InetAddress ipDestinationAddress) {
+ byte[] sourceAddress = ipDestinationAddress.getAddress();
+ fieldValues.put(DIP, sourceAddress);
+ return this;
+ }
+
+ /**
+ * Stores the IP destination address from the header
+ * @param ipDestinationAddress the destinationAddress to set
+ * @return IPv4
+ */
+ public IPv4 setDestinationAddress(int ipDestinationAddress) {
+ byte[] destinationAddress = BitBufferHelper
+ .toByteArray(ipDestinationAddress);
+ fieldValues.put(DIP, destinationAddress);
+ return this;
+ }
+
+ /**
+ * Generate a random number to set the Identification field
+ * in IPv4 Header
+ * @return short
+ */
+ private short generateId() {
+ Random randomgen = new Random();
+ return (short) (randomgen.nextInt(Short.MAX_VALUE + 1));
+ }
+
+ /**
+ * Store the options from IP header
+ * @param options - byte[]
+ * @return IPv4
+ */
+ public IPv4 setOptions(byte[] options) {
+ byte newIHL = (byte)(MIN_HEADER_SIZE >>> UNIT_SIZE_SHIFT);
+ if (options == null || options.length == 0) {
+ fieldValues.remove(OPTIONS);
+ } else {
+ int len = options.length;
+ int rlen = (len + (UNIT_SIZE - 1)) & ~(UNIT_SIZE - 1);
+ if (rlen > len) {
+ // Padding is required.
+ byte[] newopt = new byte[rlen];
+ System.arraycopy(options, 0, newopt, 0, len);
+ options = newopt;
+ len = rlen;
+ }
+ fieldValues.put(OPTIONS, options);
+ newIHL += (len >>> UNIT_SIZE_SHIFT);
+ }
+
+ setHeaderLength(newIHL);
+
+ return this;
+ }
+
+ /**
+ * Computes the IPv4 header checksum on the passed stream of bytes
+ * representing the packet
+ *
+ * @param data
+ * The byte stream
+ * @param offset
+ * The byte offset from where the IPv4 packet starts
+ * @return The computed checksum
+ */
+ short computeChecksum(byte[] data, int start) {
+ int end = start + getHeaderLen();
+ short checkSum = (short) 0;
+ int sum = 0, carry = 0, finalSum = 0;
+ int wordData;
+ int checksumStart = start
+ + (getfieldOffset(CHECKSUM) / NetUtils.NumBitsInAByte);
+
+ for (int i = start; i <= (end - 1); i = i + 2) {
+ // Skip, if the current bytes are checkSum bytes
+ if (i == checksumStart) {
+ continue;
+ }
+ wordData = ((data[i] << 8) & 0xFF00) + (data[i + 1] & 0xFF);
+ sum = sum + wordData;
+ }
+ carry = (sum >> 16) & 0xFF;
+ finalSum = (sum & 0xFFFF) + carry;
+ checkSum = (short) ~((short) finalSum & 0xFFFF);
+
+ return checkSum;
+ }
+
+ @Override
+ /**
+ * Gets the number of bits for the fieldname specified
+ * If the fieldname has variable length like "Options", then this value is computed using the header length
+ * @param fieldname - String
+ * @return number of bits for fieldname - int
+ */
+ public int getfieldnumBits(String fieldName) {
+ if (fieldName.equals(OPTIONS)) {
+ return (getHeaderLen() - MIN_HEADER_SIZE) * NetUtils.NumBitsInAByte;
+ }
+ return hdrFieldCoordMap.get(fieldName).getRight();
+ }
+
+ @Override
+ /**
+ * Method to perform post serialization - like computation of checksum of serialized header
+ * @param data
+ * @return void
+ * @Exception throws PacketException
+ */
+ protected void postSerializeCustomOperation(byte[] data)
+ throws PacketException {
+
+ // Recompute the total length field here
+ byte[] totalLength = BitBufferHelper.toByteArray((short) data.length);
+ try {
+ BitBufferHelper.setBytes(data, totalLength, getfieldOffset(TOTLENGTH),
+ getfieldnumBits(TOTLENGTH));
+ } catch (BufferException e) {
+ throw new PacketException(e.getMessage());
+ }
+
+ // Now compute the Header Checksum
+ byte[] checkSum = BitBufferHelper.toByteArray(computeChecksum(data, 0));
+
+ try {
+ BitBufferHelper.setBytes(data, checkSum, getfieldOffset(CHECKSUM),
+ getfieldnumBits(CHECKSUM));
+ } catch (BufferException e) {
+ throw new PacketException(e.getMessage());
+ }
+ }
+
+ @Override
+ /**
+ * Stores the payload of IP, serializes it and stores the length of serialized payload
+ * bytes in Total Length
+ * @param payload - Packet
+ */
+ /**
+ * Set the total length field in the IPv4 Object
+ * Note: this field will get overwritten during serialization phase.
+ */
+ public void setPayload(Packet payload) {
+ this.payload = payload;
+ /*
+ * Deriving the Total Length here
+ */
+ int payloadLength = 0;
+ if (payload != null) {
+ try {
+ payloadLength = payload.serialize().length;
+ } catch (PacketException e) {
+ logger.error("", e);
+ }
+ }
+
+ this.setTotalLength((short) (this.getHeaderLen() + payloadLength));
+ }
+
+
+ /**
+ * Method to perform post deserialization - like compare computed checksum with
+ * the one obtained from IP header
+ */
+ @Override
+ protected void postDeserializeCustomOperation(byte[] data, int startBitOffset) {
+ int start = startBitOffset / NetUtils.NumBitsInAByte;
+ short computedChecksum = computeChecksum(data, start);
+ short actualChecksum = BitBufferHelper.getShort(fieldValues.get(CHECKSUM));
+ if (computedChecksum != actualChecksum) {
+ corrupted = true;
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 - 2015 Cisco Systems, Inc. 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.packet;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.liblldp.BitBufferHelper;
+import org.opendaylight.controller.liblldp.Packet;
+
+/**
+ * Class that represents the TCP segment objects
+ */
+public class TCP extends Packet {
+
+ public static final String SRCPORT = "SourcePort";
+ public static final String DESTPORT = "DestinationPort";
+ public static final String SEQNUMBER = "SequenceNumber";
+ public static final String ACKNUMBER = "AcknowledgementNumber";
+ public static final String DATAOFFSET = "DataOffset";
+ public static final String RESERVED = "Reserved";
+ public static final String HEADERLENFLAGS = "HeaderLenFlags";
+ public static final String WINDOWSIZE = "WindowSize";
+ public static final String CHECKSUM = "Checksum";
+ public static final String URGENTPOINTER = "UrgentPointer";
+
+ private static Map<String, Pair<Integer, Integer>> fieldCoordinates = new LinkedHashMap<String, Pair<Integer, Integer>>() {
+ private static final long serialVersionUID = 1L;
+ {
+ put(SRCPORT, new ImmutablePair<Integer, Integer>(0, 16));
+ put(DESTPORT, new ImmutablePair<Integer, Integer>(16, 16));
+ put(SEQNUMBER, new ImmutablePair<Integer, Integer>(32, 32));
+ put(ACKNUMBER, new ImmutablePair<Integer, Integer>(64, 32));
+ put(DATAOFFSET, new ImmutablePair<Integer, Integer>(96, 4));
+ put(RESERVED, new ImmutablePair<Integer, Integer>(100, 3));
+ put(HEADERLENFLAGS, new ImmutablePair<Integer, Integer>(103, 9));
+ put(WINDOWSIZE, new ImmutablePair<Integer, Integer>(112, 16));
+ put(CHECKSUM, new ImmutablePair<Integer, Integer>(128, 16));
+ put(URGENTPOINTER, new ImmutablePair<Integer, Integer>(144, 16));
+ }
+ };
+
+ private final Map<String, byte[]> fieldValues;
+
+ /**
+ * Default constructor that sets all the header fields to zero
+ */
+ public TCP() {
+ super();
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ /* Setting all remaining header field values to
+ * default value of 0. These maybe changed as needed
+ */
+ setSourcePort((short) 0);
+ setDestinationPort((short) 0);
+ setSequenceNumber(0);
+ setAckNumber(0);
+ setDataOffset((byte) 0);
+ setReserved((byte) 0);
+ setWindowSize((short) 0);
+ setUrgentPointer((short) 0);
+ setChecksum((short) 0);
+ }
+
+ /**
+ * Constructor that sets the access level for the packet and
+ * sets all the header fields to zero.
+ * @param writeAccess - boolean
+ */
+ public TCP(boolean writeAccess) {
+ super(writeAccess);
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ /* Setting all remaining header field values to
+ * default value of 0. These maybe changed as needed
+ */
+ setSourcePort((short) 0);
+ setDestinationPort((short) 0);
+ setSequenceNumber(0);
+ setAckNumber(0);
+ setDataOffset((byte) 0);
+ setReserved((byte) 0);
+ setWindowSize((short) 0);
+ setUrgentPointer((short) 0);
+ setChecksum((short) 0);
+ }
+
+ @Override
+ /**
+ * Stores the value read from data stream
+ * @param headerField - String
+ * @param readValue - byte[]
+ */
+ public void setHeaderField(String headerField, byte[] readValue) {
+ hdrFieldsMap.put(headerField, readValue);
+ }
+
+ /**
+ * Sets the TCP source port for the current TCP object instance
+ * @param tcpSourcePort short
+ * @return TCP
+ */
+ public TCP setSourcePort(short tcpSourcePort) {
+ byte[] sourcePort = BitBufferHelper.toByteArray(tcpSourcePort);
+ fieldValues.put(SRCPORT, sourcePort);
+ return this;
+ }
+
+ /**
+ * Sets the TCP destination port for the current TCP object instance
+ * @param tcpDestinationPort short
+ * @return TCP
+ */
+ public TCP setDestinationPort(short tcpDestinationPort) {
+ byte[] destinationPort = BitBufferHelper
+ .toByteArray(tcpDestinationPort);
+ fieldValues.put(DESTPORT, destinationPort);
+ return this;
+ }
+
+ /**
+ * Sets the TCP sequence number for the current TCP object instance
+ * @param tcpSequenceNumber - int
+ * @return TCP
+ */
+ public TCP setSequenceNumber(int tcpSequenceNumber) {
+ byte[] sequenceNumber = BitBufferHelper.toByteArray(tcpSequenceNumber);
+ fieldValues.put(SEQNUMBER, sequenceNumber);
+ return this;
+ }
+
+ /**
+ * Sets the TCP data offset for the current TCP object instance
+ * @param tcpDataOffset - byte
+ * @return TCP
+ */
+ public TCP setDataOffset(byte tcpDataOffset) {
+ byte[] offset = BitBufferHelper.toByteArray(tcpDataOffset);
+ fieldValues.put("DataOffset", offset);
+ return this;
+ }
+
+ /**
+ * Sets the TCP reserved bits for the current TCP object instance
+ * @param tcpReserved byte
+ * @return TCP
+ */
+ public TCP setReserved(byte tcpReserved) {
+ byte[] reserved = BitBufferHelper.toByteArray(tcpReserved);
+ fieldValues.put("Reserved", reserved);
+ return this;
+ }
+
+ /**
+ * Sets the TCP Ack number for the current TCP object instance
+ * @param tcpAckNumber int
+ * @return TCP
+ */
+ public TCP setAckNumber(int tcpAckNumber) {
+ byte[] ackNumber = BitBufferHelper.toByteArray(tcpAckNumber);
+ fieldValues.put(ACKNUMBER, ackNumber);
+ return this;
+ }
+
+ /**
+ * Sets the TCP flags for the current TCP object instance
+ * @param tcpFlags short
+ * @return TCP
+ */
+ public TCP setHeaderLenFlags(short tcpFlags) {
+ byte[] headerLenFlags = BitBufferHelper.toByteArray(tcpFlags);
+ fieldValues.put(HEADERLENFLAGS, headerLenFlags);
+ return this;
+ }
+
+ /**
+ * Sets the TCP window size for the current TCP object instance
+ * @param tcpWsize short
+ * @return TCP
+ */
+ public TCP setWindowSize(short tcpWsize) {
+ byte[] wsize = BitBufferHelper.toByteArray(tcpWsize);
+ fieldValues.put(WINDOWSIZE, wsize);
+ return this;
+ }
+
+ /**
+ * Sets the TCP checksum for the current TCP object instance
+ * @param tcpChecksum short
+ * @return TCP
+ */
+ public TCP setChecksum(short tcpChecksum) {
+ byte[] checksum = BitBufferHelper.toByteArray(tcpChecksum);
+ fieldValues.put(CHECKSUM, checksum);
+ return this;
+ }
+
+ /**
+ * Sets the TCP Urgent Pointer for the current TCP object instance
+ * @param tcpUrgentPointer short
+ * @return TCP
+ */
+ public TCP setUrgentPointer(short tcpUrgentPointer) {
+ byte[] urgentPointer = BitBufferHelper.toByteArray(tcpUrgentPointer);
+ fieldValues.put(URGENTPOINTER, urgentPointer);
+ return this;
+ }
+
+ /**
+ * Gets the stored source port value of TCP header
+ * @return the sourcePort
+ */
+ public short getSourcePort() {
+ return (BitBufferHelper.getShort(fieldValues.get(SRCPORT)));
+ }
+
+ /**
+ * Gets the stored destination port value of TCP header
+ * @return the destinationPort
+ */
+ public short getDestinationPort() {
+ return (BitBufferHelper.getShort(fieldValues.get(DESTPORT)));
+ }
+
+ /**
+ * Get the stored checksum value of the TCP header
+ * @return short - the checksum
+ */
+ public short getChecksum() {
+ return (BitBufferHelper.getShort(fieldValues.get(CHECKSUM)));
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 - 2015 Cisco Systems, Inc. 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.packet;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.liblldp.BitBufferHelper;
+import org.opendaylight.controller.liblldp.Packet;
+
+/**
+ * Class that represents the UDP datagram objects
+ */
+
+public class UDP extends Packet {
+
+ private static final String SRCPORT = "SourcePort";
+ private static final String DESTPORT = "DestinationPort";
+ private static final String LENGTH = "Length";
+ private static final String CHECKSUM = "Checksum";
+
+ private static Map<String, Pair<Integer, Integer>> fieldCoordinates = new LinkedHashMap<String, Pair<Integer, Integer>>() {
+ private static final long serialVersionUID = 1L;
+ {
+ put(SRCPORT, new ImmutablePair<Integer, Integer>(0, 16));
+ put(DESTPORT, new ImmutablePair<Integer, Integer>(16, 16));
+ put(LENGTH, new ImmutablePair<Integer, Integer>(32, 16));
+ put(CHECKSUM, new ImmutablePair<Integer, Integer>(48, 16));
+ }
+ };
+
+ public UDP() {
+ super();
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ /* Setting all remaining header field values to
+ * default value of 0. These maybe changed as needed
+ */
+ setSourcePort((short) 0);
+ setDestinationPort((short) 0);
+ setChecksum((short) 0);
+ }
+
+ public UDP(boolean writeAccess) {
+ super(writeAccess);
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ /* Setting all remaining header field values to
+ * default value of 0. These maybe changed as needed
+ */
+ setSourcePort((short) 0);
+ setDestinationPort((short) 0);
+ setChecksum((short) 0);
+ }
+
+ private final Map<String, byte[]> fieldValues;
+
+ /* public static Map<Short, Class<? extends Packet>> decodeMap;
+
+ static {
+ decodeMap = new HashMap<Short, Class<? extends Packet>>();
+ UDP.decodeMap.put((short)67, DHCP.class);
+ UDP.decodeMap.put((short)68, DHCP.class);
+ }*/
+ /**
+ * Get the stored source port
+ * @return short - the sourcePort
+ */
+ public short getSourcePort() {
+ return (BitBufferHelper.getShort(fieldValues.get(SRCPORT)));
+ }
+
+ /**
+ * Get the stored destination port
+ * @return short - the destinationPort
+ */
+ public short getDestinationPort() {
+ return (BitBufferHelper.getShort(fieldValues.get(DESTPORT)));
+ }
+
+ /**
+ * Gets the stored length of UDP header
+ * @return short - the length
+ */
+ public short getLength() {
+ return (BitBufferHelper.getShort(fieldValues.get(LENGTH)));
+ }
+
+ /**
+ * Get the stored checksum value of the UDP header
+ * @return short - the checksum
+ */
+ public short getChecksum() {
+ return (BitBufferHelper.getShort(fieldValues.get(CHECKSUM)));
+ }
+
+ @Override
+ /**
+ * Store the value read from data stream in hdrFieldMap
+ */
+ public void setHeaderField(String headerField, byte[] readValue) {
+ hdrFieldsMap.put(headerField, readValue);
+ }
+
+ /**
+ * Sets the sourcePort value for the current UDP object instance
+ * @param udpSourcePort short source port to set
+ * @return UDP
+ */
+ public UDP setSourcePort(short udpSourcePort) {
+ byte[] sourcePort = BitBufferHelper.toByteArray(udpSourcePort);
+ fieldValues.put(SRCPORT, sourcePort);
+ return this;
+ }
+
+ /**
+ * Sets the destinationPort value for the current UDP object instance
+ * @param udpDestinationPort short destination port to set
+ * @return UDP
+ */
+ public UDP setDestinationPort(short udpDestinationPort) {
+ byte[] destinationPort = BitBufferHelper
+ .toByteArray(udpDestinationPort);
+ fieldValues.put(DESTPORT, destinationPort);
+ return this;
+ }
+
+ /**
+ * Set the UDP header length value for the current UDP object instance
+ * @param udpLength - short - the length to set
+ * @return UDP
+ */
+ public UDP setLength(short udpLength) {
+ byte[] length = BitBufferHelper.toByteArray(udpLength);
+ fieldValues.put(LENGTH, length);
+ return this;
+ }
+
+ /**
+ * Set the checksum for the current UDP object instance
+ * @param udpChecksum - short - the checksum to set
+ * @return UDP
+ */
+ public UDP setChecksum(short udpChecksum) {
+ byte[] checksum = BitBufferHelper.toByteArray(udpChecksum);
+ fieldValues.put(CHECKSUM, checksum);
+ return this;
+ }
+
+}
--- /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.utils;
+
+import org.opendaylight.yangtools.util.PropertyUtils;
+
+public class SystemPropertyReader {
+ public static class Cluster {
+ // Sleep time to be used between successive EntityOwnershipState calls
+ // Returned time is in milliseconds
+ public static long getSleepTimeBetweenRetries() {
+ return Long.getLong("cluster.entity_owner.sleep_time_between_retries", 1000);
+ }
+
+ // Returns max. retries to be tried with EntityOwnershipState calls
+ public static int getMaxRetries() {
+ return Integer.getInteger("cluster.entity_owner.max_retries", 5);
+ }
+ }
+
+ // Returns max retries to be tried with DataStoreJobCoordinator calls
+ public static int getDataStoreJobCoordinatorMaxRetries() {
+ return Integer.getInteger("datastore.job_coordinator.max_retries", 5);
+ }
+}
--- /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.utils.cache;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public class CacheUtil {
+ private static final ConcurrentMap<String, ConcurrentMap<?, ?>> m_mapCache =
+ new ConcurrentHashMap<String, ConcurrentMap<?, ?>>();
+
+ public static ConcurrentMap<?, ?> getCache(String sCacheName) {
+ return m_mapCache.get(sCacheName);
+ }
+
+ public static void createCache(String sCacheName) {
+ if (m_mapCache.get(sCacheName) == null)
+ m_mapCache.put(sCacheName, new ConcurrentHashMap<Object, Object>());
+ }
+
+ public static void destroyCache(String sCacheName) {
+ m_mapCache.remove(sCacheName);
+ }
+}
--- /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.utils.clustering;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipState;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.utils.SystemPropertyReader;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+public class ClusteringUtils {
+
+ static DataStoreJobCoordinator dataStoreJobCoordinator;
+
+ static DataStoreJobCoordinator getDataStoreJobCoordinator() {
+ if (dataStoreJobCoordinator == null) {
+ dataStoreJobCoordinator = DataStoreJobCoordinator.getInstance();
+ }
+ return dataStoreJobCoordinator;
+ }
+ public static void setDataStoreJobCoordinator(DataStoreJobCoordinator ds) {
+ dataStoreJobCoordinator = ds;
+ }
+
+ public static ListenableFuture<Boolean> checkNodeEntityOwner(EntityOwnershipService entityOwnershipService,
+ String entityType, String nodeId) {
+ return checkNodeEntityOwner(entityOwnershipService, new Entity(entityType, nodeId),
+ SystemPropertyReader.Cluster.getSleepTimeBetweenRetries(), SystemPropertyReader.Cluster.getMaxRetries());
+ }
+
+ public static ListenableFuture<Boolean> checkNodeEntityOwner(EntityOwnershipService entityOwnershipService,
+ String entityType, YangInstanceIdentifier nodeId) {
+ return checkNodeEntityOwner(entityOwnershipService, new Entity(entityType, nodeId),
+ SystemPropertyReader.Cluster.getSleepTimeBetweenRetries(), SystemPropertyReader.Cluster.getMaxRetries());
+ }
+
+ public static ListenableFuture<Boolean> checkNodeEntityOwner(EntityOwnershipService entityOwnershipService,
+ Entity entity, long sleepBetweenRetries, int maxRetries) {
+ SettableFuture<Boolean> checkNodeEntityfuture = SettableFuture.create();
+ CheckEntityOwnerTask checkEntityOwnerTask = new CheckEntityOwnerTask(entityOwnershipService, entity,
+ checkNodeEntityfuture, sleepBetweenRetries, maxRetries);
+ getDataStoreJobCoordinator().enqueueJob(entityOwnershipService.toString(), checkEntityOwnerTask);
+ return checkNodeEntityfuture;
+ }
+
+ private static class CheckEntityOwnerTask implements Callable<List<ListenableFuture<Void>>> {
+ EntityOwnershipService entityOwnershipService;
+ Entity entity;
+ SettableFuture<Boolean> checkNodeEntityfuture;
+ long sleepBetweenRetries;
+ int retries;
+
+ public CheckEntityOwnerTask(EntityOwnershipService entityOwnershipService, Entity entity,
+ SettableFuture<Boolean> checkNodeEntityfuture, long sleepBetweenRetries, int retries) {
+ this.entityOwnershipService = entityOwnershipService;
+ this.entity = entity;
+ this.checkNodeEntityfuture = checkNodeEntityfuture;
+ this.sleepBetweenRetries = sleepBetweenRetries;
+ this.retries = retries;
+ }
+
+ @Override
+ public List<ListenableFuture<Void>> call() throws Exception {
+ while (retries > 0) {
+ retries = retries - 1;
+ Optional<EntityOwnershipState> entityState = entityOwnershipService.getOwnershipState(entity);
+ if (entityState.isPresent()) {
+ EntityOwnershipState entityOwnershipState = entityState.get();
+ if (entityOwnershipState.hasOwner()) {
+ checkNodeEntityfuture.set(entityOwnershipState.isOwner());
+ return getResultFuture();
+ }
+ }
+ Thread.sleep(sleepBetweenRetries);
+ }
+ checkNodeEntityfuture.setException(new EntityOwnerNotPresentException("Entity Owner Not Present"));
+ return getResultFuture();
+ }
+
+ private List<ListenableFuture<Void>> getResultFuture() {
+ ListenableFuture<Void> future = Futures.immediateFuture(null);
+ ArrayList<ListenableFuture<Void>> futureList = Lists.newArrayList();
+ futureList.add(future);
+ return futureList;
+ }
+ }
+}
--- /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.utils.clustering;
+
+public class EntityOwnerNotPresentException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ public EntityOwnerNotPresentException() {
+ }
+
+ public EntityOwnerNotPresentException(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.utils.clustering;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+import org.opendaylight.controller.md.sal.common.api.clustering.*;
+import org.opendaylight.vpnservice.datastoreutils.DataStoreJobCoordinator;
+import org.opendaylight.vpnservice.utils.SystemPropertyReader;
+import org.opendaylight.vpnservice.utils.cache.CacheUtil;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentMap;
+
+public class EntityOwnerUtils {
+ public static final String ENTITY_OWNER_CACHE = "entity.owner.cache";
+ private static final Logger LOG = LoggerFactory.getLogger(EntityOwnerUtils.class);
+
+ static {
+ createEntityOwnerCache();
+ }
+ private static void createEntityOwnerCache() {
+ if (CacheUtil.getCache(ENTITY_OWNER_CACHE) == null) {
+ CacheUtil.createCache(ENTITY_OWNER_CACHE);
+ }
+ }
+
+ private static String getEntity(String entityType, String entityName) {
+ return entityType;
+ }
+
+ private static void updateEntityOwner(String entityType, String entityName, Boolean isOwner) {
+ ConcurrentMap<String, Boolean> entityOwnerCache =
+ (ConcurrentMap<String, Boolean>) CacheUtil.getCache(ENTITY_OWNER_CACHE);
+ String entity = getEntity(entityType, entityName);
+ if (entityOwnerCache != null) {
+ LOG.trace("updating entity owner "+isOwner+ " "+entity );
+ entityOwnerCache.put(entity, isOwner);
+ }
+ }
+
+ public static boolean amIEntityOwner(String entityType, String entityName) {
+ ConcurrentMap<String, Boolean> entityOwnerCache =
+ (ConcurrentMap<String, Boolean>) CacheUtil.getCache(ENTITY_OWNER_CACHE);
+ String entity = getEntity(entityType, entityName);
+ boolean ret = false;
+ if (entityOwnerCache != null) {
+ if (entityOwnerCache.get(entity) != null) {
+ ret = entityOwnerCache.get(entity);
+ }
+ } else {
+ LOG.error("entity owner cache null");
+ }
+ LOG.trace("get entity owner result {} for type {}" ,ret ,entity);
+ return ret;
+ }
+
+ /**
+ * Registers the entityName for ownership for given entityType
+ * adds a local listener which takes care of updating the cached entity status
+ * @param entityOwnershipService
+ * @param entityType
+ * @param entityName
+ * @param listener also adds this listener for ownership events if provided
+ * @throws CandidateAlreadyRegisteredException
+ */
+ public static void registerEntityCandidateForOwnerShip (
+ EntityOwnershipService entityOwnershipService,
+ String entityType, String entityName, EntityOwnershipListener listener)
+ throws CandidateAlreadyRegisteredException {
+ LOG.info("registering for entity ownership for type "+entityType);
+ Entity candidateEntity = new Entity(entityType, entityName);
+ EntityOwnershipCandidateRegistration candidateRegistration = entityOwnershipService.registerCandidate(
+ candidateEntity);
+ EntityOwnershipListenerRegistration listenerRegistration = entityOwnershipService.registerListener(entityType,
+ entityOwnershipListener);
+ if (listener != null) {
+ entityOwnershipService.registerListener(entityType, listener);
+ }
+ LOG.info("registered for entity ownership for type "+entityType);
+ //TODO track registrations for closing
+ }
+
+ private static Listener entityOwnershipListener = new Listener();
+ static class Listener implements EntityOwnershipListener {
+
+ @Override
+ public void ownershipChanged(EntityOwnershipChange ownershipChange) {
+ String entityType = ownershipChange.getEntity().getType();
+ String entityName = ownershipChange.getEntity().getId().toString();
+ LOG.info("entity ownership changed for "+entityType);
+ if (ownershipChange.hasOwner() && ownershipChange.isOwner()) {
+ LOG.info("entity ownership change became owner for type "+entityType);
+ updateEntityOwner(entityType, entityName, Boolean.TRUE);
+ } else {
+ LOG.info("entity ownership lost ownership for type "+entityType);
+ updateEntityOwner(entityType, entityName, Boolean.FALSE);
+ }
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.utils.hwvtep;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeVxlanOverIpv4;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+
+import com.google.common.collect.ImmutableBiMap;
+
+// TODO (eperefr) Remove this class once it's been added to hwvtep-southbound
+public class HwvtepSouthboundConstants {
+
+ public static final TopologyId HWVTEP_TOPOLOGY_ID = new TopologyId("hwvtep:1");
+ public static final String HWVTEP_ENTITY_TYPE = "hwvtep";
+ public static final Object PSWITCH_URI_PREFIX = "physicalswitch";
+ public static final ImmutableBiMap<Class<? extends EncapsulationTypeBase>, String> ENCAPS_TYPE_MAP = new ImmutableBiMap.Builder<Class<? extends EncapsulationTypeBase>, String>()
+ .put(EncapsulationTypeVxlanOverIpv4.class, "vxlan_over_ipv4").build();
+ public static final String ELAN_ENTITY_TYPE = "elan";
+ public static final String ELAN_ENTITY_NAME = "elan";
+ public static final String TEP_PREFIX = "vxlan_over_ipv4:";
+}
--- /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.utils.hwvtep;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+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.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.EncapsulationTypeVxlanOverIpv4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalPortAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitchesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitchesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.locator.set.attributes.LocatorSetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindings;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindingsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindingsKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableBiMap;
+
+/**
+ * TODO: Move these API's to ovsdb's utils.hwvtepsouthbound-utils module.
+ */
+public class HwvtepSouthboundUtils {
+
+ /**
+ * Creates the hwvtep topology instance identifier.
+ *
+ * @return the instance identifier
+ */
+ public static InstanceIdentifier<Topology> createHwvtepTopologyInstanceIdentifier() {
+ return InstanceIdentifier.create(NetworkTopology.class).child(Topology.class,
+ new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID));
+ }
+
+ /**
+ * Creates the instance identifier.
+ *
+ * @param nodeId
+ * the node id
+ * @return the instance identifier
+ */
+ public static InstanceIdentifier<Node> createInstanceIdentifier(NodeId nodeId) {
+ return InstanceIdentifier.create(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID))
+ .child(Node.class, new NodeKey(nodeId));
+ }
+
+
+ public static InstanceIdentifier<TerminationPoint> createTerminationPointId(NodeId nodeId,
+ TerminationPointKey tpKey) {
+ return createInstanceIdentifier(nodeId).child(TerminationPoint.class, tpKey);
+ }
+ /**
+ * Creates the logical switches instance identifier.
+ *
+ * @param nodeId
+ * the node id
+ * @param hwvtepNodeName
+ * the hwvtep node name
+ * @return the instance identifier
+ */
+ public static InstanceIdentifier<LogicalSwitches> createLogicalSwitchesInstanceIdentifier(NodeId nodeId,
+ HwvtepNodeName hwvtepNodeName) {
+ return createInstanceIdentifier(nodeId).augmentation(HwvtepGlobalAugmentation.class)
+ .child(LogicalSwitches.class, new LogicalSwitchesKey(hwvtepNodeName));
+ }
+
+ /**
+ * Creates the remote ucast macs instance identifier.
+ *
+ * @param nodeId
+ * the node id
+ * @param mac
+ * the mac
+ * @return the instance identifier
+ */
+ public static InstanceIdentifier<RemoteUcastMacs> createRemoteUcastMacsInstanceIdentifier(NodeId nodeId,
+ String logicalSwitchName,
+ MacAddress mac) {
+ InstanceIdentifier<LogicalSwitches> logicalSwitch = createLogicalSwitchesInstanceIdentifier(nodeId,
+ new HwvtepNodeName(logicalSwitchName));
+ return createInstanceIdentifier(nodeId).augmentation(HwvtepGlobalAugmentation.class)
+ .child(RemoteUcastMacs.class, new RemoteUcastMacsKey(new HwvtepLogicalSwitchRef(logicalSwitch), mac));
+ }
+
+ /**
+ * Creates the local ucast macs instance identifier.
+ *
+ * @param nodeId
+ * the node id
+ * @param mac
+ * the mac
+ * @return the instance identifier
+ */
+ public static InstanceIdentifier<LocalUcastMacs> createLocalUcastMacsInstanceIdentifier(NodeId nodeId,
+ String logicalSwitchName,
+ MacAddress mac) {
+ InstanceIdentifier<LogicalSwitches> logicalSwitch = createLogicalSwitchesInstanceIdentifier(nodeId,
+ new HwvtepNodeName(logicalSwitchName));
+ return createInstanceIdentifier(nodeId).augmentation(HwvtepGlobalAugmentation.class).child(LocalUcastMacs.class,
+ new LocalUcastMacsKey(new HwvtepLogicalSwitchRef(logicalSwitch), mac));
+ }
+
+ /**
+ * Creates the remote mcast macs instance identifier.
+ *
+ * @param nodeId
+ * the node id
+ * @param logicalSwitchName
+ * the logical switch name
+ * @param mac
+ * the mac
+ * @return the instance identifier
+ */
+ public static InstanceIdentifier<RemoteMcastMacs> createRemoteMcastMacsInstanceIdentifier(NodeId nodeId,
+ String logicalSwitchName, MacAddress mac) {
+ InstanceIdentifier<LogicalSwitches> logicalSwitch = createLogicalSwitchesInstanceIdentifier(nodeId,
+ new HwvtepNodeName(logicalSwitchName));
+ return createInstanceIdentifier(nodeId).augmentation(HwvtepGlobalAugmentation.class)
+ .child(RemoteMcastMacs.class, new RemoteMcastMacsKey(new HwvtepLogicalSwitchRef(logicalSwitch), mac));
+ }
+
+ /**
+ * Creates the remote mcast macs instance identifier.
+ *
+ * @param nodeId
+ * the node id
+ * @param remoteMcastMacsKey
+ * the remote mcast macs key
+ * @return the instance identifier
+ */
+ public static InstanceIdentifier<RemoteMcastMacs> createRemoteMcastMacsInstanceIdentifier(NodeId nodeId,
+ RemoteMcastMacsKey remoteMcastMacsKey) {
+ return createInstanceIdentifier(nodeId).augmentation(HwvtepGlobalAugmentation.class)
+ .child(RemoteMcastMacs.class, remoteMcastMacsKey);
+ }
+
+ /**
+ * Creates the physical locator instance identifier.
+ *
+ * @param nodeId
+ * the node id
+ * @param physicalLocatorAug
+ * the physical locator aug
+ * @return the instance identifier
+ */
+ public static InstanceIdentifier<TerminationPoint> createPhysicalLocatorInstanceIdentifier(NodeId nodeId,
+ HwvtepPhysicalLocatorAugmentation physicalLocatorAug) {
+ return createInstanceIdentifier(nodeId).child(TerminationPoint.class,
+ getTerminationPointKey(physicalLocatorAug));
+ }
+
+ /**
+ * Creates the physical port instance identifier.
+ *
+ * @param physicalSwitchNodeId
+ * the physical switch node id
+ * @param phyPortName
+ * the phy port name
+ * @return the instance identifier
+ */
+ public static InstanceIdentifier<HwvtepPhysicalPortAugmentation> createPhysicalPortInstanceIdentifier(
+ NodeId physicalSwitchNodeId, String phyPortName) {
+ return createInstanceIdentifier(physicalSwitchNodeId)
+ .child(TerminationPoint.class, new TerminationPointKey(new TpId(phyPortName)))
+ .augmentation(HwvtepPhysicalPortAugmentation.class);
+ }
+
+ /**
+ * Creates the vlan binding instance identifier.
+ *
+ * @param physicalSwitchNodeId
+ * the physical switch node id
+ * @param phyPortName
+ * the phy port name
+ * @param vlanId
+ * the vlan id
+ * @return the instance identifier
+ */
+ public static InstanceIdentifier<VlanBindings> createVlanBindingInstanceIdentifier(NodeId physicalSwitchNodeId,
+ String phyPortName, Integer vlanId) {
+ return createPhysicalPortInstanceIdentifier(physicalSwitchNodeId, phyPortName).child(VlanBindings.class,
+ new VlanBindingsKey(new VlanId(vlanId)));
+ }
+
+ /**
+ * Gets the termination point key.
+ *
+ * @param phyLocator
+ * the phy locator
+ * @return the termination point key
+ */
+ public static TerminationPointKey getTerminationPointKey(HwvtepPhysicalLocatorAugmentation phyLocator) {
+ TerminationPointKey tpKey = null;
+ if (phyLocator.getEncapsulationType() != null && phyLocator.getDstIp() != null) {
+ String encapType = HwvtepSouthboundConstants.ENCAPS_TYPE_MAP.get(phyLocator.getEncapsulationType());
+ String tpKeyStr = encapType + ":" + String.valueOf(phyLocator.getDstIp().getValue());
+ tpKey = new TerminationPointKey(new TpId(tpKeyStr));
+ }
+ return tpKey;
+ }
+
+ /**
+ * Creates the managed node id.
+ *
+ * @param nodeId
+ * the node id
+ * @param physicalSwitchName
+ * the physical switch name
+ * @return the node id
+ */
+ public static NodeId createManagedNodeId(NodeId nodeId, String physicalSwitchName) {
+ String phySwitchNodeId = nodeId.getValue() + "/" + HwvtepSouthboundConstants.PSWITCH_URI_PREFIX + "/"
+ + physicalSwitchName;
+ return new NodeId(phySwitchNodeId);
+ }
+
+ /**
+ * Create logical switch.
+ *
+ * @param name
+ * the name
+ * @param desc
+ * the desc
+ * @param tunnelKey
+ * the tunnel key
+ * @return the logical switches
+ */
+ public static LogicalSwitches createLogicalSwitch(String name, String desc, String tunnelKey) {
+ HwvtepNodeName hwvtepName = new HwvtepNodeName(name);
+ LogicalSwitchesBuilder lsBuilder = new LogicalSwitchesBuilder().setHwvtepNodeDescription(desc)
+ .setHwvtepNodeName(hwvtepName).setKey(new LogicalSwitchesKey(hwvtepName)).setTunnelKey(tunnelKey);
+ return lsBuilder.build();
+ }
+
+ /**
+ * Create hwvtep physical locator augmentation.
+ *
+ * @param ipAddress
+ * the ip address
+ * @return the hwvtep physical locator augmentation
+ */
+ public static HwvtepPhysicalLocatorAugmentation createHwvtepPhysicalLocatorAugmentation(String ipAddress) {
+ // FIXME: Get encapsulation type dynamically
+ Class<? extends EncapsulationTypeBase> encapTypeClass = createEncapsulationType(StringUtils.EMPTY);
+ HwvtepPhysicalLocatorAugmentationBuilder phyLocBuilder = new HwvtepPhysicalLocatorAugmentationBuilder()
+ .setEncapsulationType(encapTypeClass).setDstIp(new IpAddress(ipAddress.toCharArray()));
+ return phyLocBuilder.build();
+ }
+
+ public static Class<? extends EncapsulationTypeBase> createEncapsulationType(String type) {
+ Preconditions.checkNotNull(type);
+ if (type.isEmpty()) {
+ return EncapsulationTypeVxlanOverIpv4.class;
+ } else {
+ ImmutableBiMap<String, Class<? extends EncapsulationTypeBase>> mapper = HwvtepSouthboundConstants.ENCAPS_TYPE_MAP
+ .inverse();
+ return mapper.get(type);
+ }
+ }
+
+ /**
+ * Create remote ucast mac.
+ *
+ * @param nodeId
+ * the node id
+ * @param mac
+ * the mac
+ * @param ipAddress
+ * the ip address
+ * @param logicalSwitchName
+ * the logical switch name
+ * @param physicalLocatorAug
+ * the physical locator aug
+ * @return the remote ucast macs
+ */
+ public static RemoteUcastMacs createRemoteUcastMac(NodeId nodeId, String mac, IpAddress ipAddress,
+ String logicalSwitchName, HwvtepPhysicalLocatorAugmentation physicalLocatorAug) {
+ HwvtepLogicalSwitchRef lsRef = new HwvtepLogicalSwitchRef(
+ createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName)));
+ HwvtepPhysicalLocatorRef phyLocRef = new HwvtepPhysicalLocatorRef(
+ createPhysicalLocatorInstanceIdentifier(nodeId, physicalLocatorAug));
+
+ RemoteUcastMacs remoteUcastMacs = new RemoteUcastMacsBuilder().setMacEntryKey(new MacAddress(mac))
+ .setIpaddr(ipAddress).setLogicalSwitchRef(lsRef).setLocatorRef(phyLocRef).build();
+ return remoteUcastMacs;
+ }
+
+ /**
+ * Creates the remote mcast mac.
+ *
+ * @param nodeId
+ * the node id
+ * @param mac
+ * the mac
+ * @param ipAddress
+ * the ip address
+ * @param logicalSwitchName
+ * the logical switch name
+ * @param lstPhysicalLocatorAug
+ * the lst physical locator aug
+ * @return the remote mcast macs
+ */
+ public static RemoteMcastMacs createRemoteMcastMac(NodeId nodeId, String mac, IpAddress ipAddress,
+ String logicalSwitchName, List<HwvtepPhysicalLocatorAugmentation> lstPhysicalLocatorAug) {
+ HwvtepLogicalSwitchRef lsRef = new HwvtepLogicalSwitchRef(
+ createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName)));
+
+ List<LocatorSet> lstLocatorSet = new ArrayList<>();
+ for (HwvtepPhysicalLocatorAugmentation phyLocatorAug : lstPhysicalLocatorAug) {
+ HwvtepPhysicalLocatorRef phyLocRef = new HwvtepPhysicalLocatorRef(
+ createPhysicalLocatorInstanceIdentifier(nodeId, phyLocatorAug));
+ lstLocatorSet.add(new LocatorSetBuilder().setLocatorRef(phyLocRef).build());
+ }
+
+ RemoteMcastMacs remoteMcastMacs = new RemoteMcastMacsBuilder().setMacEntryKey(new MacAddress(mac))
+ .setIpaddr(ipAddress).setLogicalSwitchRef(lsRef).setLocatorSet(lstLocatorSet).build();
+ return remoteMcastMacs;
+ }
+
+ /**
+ * Create vlan binding.
+ *
+ * @param nodeId
+ * the node id
+ * @param vlanId
+ * the vlan id
+ * @param logicalSwitchName
+ * the logical switch name
+ * @return the vlan bindings
+ */
+ public static VlanBindings createVlanBinding(NodeId nodeId, int vlanId, String logicalSwitchName) {
+ VlanBindingsBuilder vbBuilder = new VlanBindingsBuilder();
+ VlanBindingsKey vbKey = new VlanBindingsKey(new VlanId(vlanId));
+ vbBuilder.setKey(vbKey);
+ vbBuilder.setVlanIdKey(vbKey.getVlanIdKey());
+
+ final InstanceIdentifier<LogicalSwitches> lSwitchIid = createLogicalSwitchesInstanceIdentifier(nodeId,
+ new HwvtepNodeName(logicalSwitchName));
+ HwvtepLogicalSwitchRef lsRef = new HwvtepLogicalSwitchRef(lSwitchIid);
+ vbBuilder.setLogicalSwitchRef(lsRef);
+ return vbBuilder.build();
+ }
+
+ public static TerminationPointKey getTerminationPointKey(String ipAddress) {
+ TerminationPointKey tpKey = null;
+ String tpKeyStr = getTerminationPointKeyString(ipAddress);
+ if(tpKeyStr != null) {
+ tpKey = new TerminationPointKey(new TpId(tpKeyStr));
+ }
+ return tpKey;
+ }
+ public static String getTerminationPointKeyString(String ipAddress) {
+ String tpKeyStr = null;
+ if(ipAddress != null) {
+ tpKeyStr = new StringBuilder(HwvtepSouthboundConstants.TEP_PREFIX).
+ append(ipAddress).toString();
+ }
+ return tpKeyStr;
+ }
+
+}
--- /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.utils.hwvtep;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+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.yang.types.rev130715.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.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalPortAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalPortAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical.port.attributes.VlanBindings;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Utility class to related to Hardware VTEP devices.
+ */
+public final class HwvtepUtils {
+
+ // TODO: (eperefr) Move this to HwvtepSouthboundUtils when in place.
+ public static InstanceIdentifier<LocalUcastMacs> getWildCardPathForLocalUcastMacs() {
+ return InstanceIdentifier.create(NetworkTopology.class).child(Topology.class).child(Node.class)
+ .augmentation(HwvtepGlobalAugmentation.class).child(LocalUcastMacs.class);
+ }
+
+ /**
+ * Adds the logical switch into config DS.
+ *
+ * @param broker
+ * the broker
+ * @param nodeId
+ * the node id
+ * @param logicalSwitch
+ * the logical switch
+ * @return the listenable future
+ */
+ public static ListenableFuture<Void> addLogicalSwitch(DataBroker broker, NodeId nodeId,
+ LogicalSwitches logicalSwitch) {
+ WriteTransaction transaction = broker.newWriteOnlyTransaction();
+ putLogicalSwitch(transaction,LogicalDatastoreType.CONFIGURATION, nodeId, logicalSwitch);
+ return transaction.submit();
+ }
+
+ public static ListenableFuture<Void> addLogicalSwitch(DataBroker broker, LogicalDatastoreType logicalDatastoreType,
+ NodeId nodeId,
+ LogicalSwitches logicalSwitch) {
+ WriteTransaction transaction = broker.newWriteOnlyTransaction();
+ putLogicalSwitch(transaction,logicalDatastoreType, nodeId, logicalSwitch);
+ return transaction.submit();
+ }
+ /**
+ * Put the logical switches in the transaction.
+ *
+ * @param transaction
+ * the transaction
+ * @param nodeId
+ * the node id
+ * @param lstSwitches
+ * the lst switches
+ */
+ public static void putLogicalSwitches(final WriteTransaction transaction, final NodeId nodeId,
+ final List<LogicalSwitches> lstSwitches) {
+ if (lstSwitches != null) {
+ for (LogicalSwitches logicalSwitch : lstSwitches) {
+ putLogicalSwitch(transaction,LogicalDatastoreType.CONFIGURATION, nodeId, logicalSwitch);
+ }
+ }
+ }
+
+ /**
+ * Put logical switch in the transaction.
+ *
+ * @param transaction
+ * the transaction
+ * @param nodeId
+ * the node id
+ * @param logicalSwitch
+ * the logical switch
+ */
+ public static void putLogicalSwitch(final WriteTransaction transaction,LogicalDatastoreType logicalDatastoreType,
+ final NodeId nodeId, final LogicalSwitches logicalSwitch) {
+ InstanceIdentifier<LogicalSwitches> iid = HwvtepSouthboundUtils.createLogicalSwitchesInstanceIdentifier(nodeId,
+ logicalSwitch.getHwvtepNodeName());
+ transaction.put(logicalDatastoreType, iid, logicalSwitch, true);
+ }
+
+ /**
+ * Delete logical switch from config DS.
+ *
+ * @param broker
+ * the broker
+ * @param nodeId
+ * the node id
+ * @param logicalSwitchName
+ * the logical switch name
+ * @return the listenable future
+ */
+ public static ListenableFuture<Void> deleteLogicalSwitch(DataBroker broker, NodeId nodeId,
+ String logicalSwitchName) {
+ WriteTransaction transaction = broker.newWriteOnlyTransaction();
+ deleteLogicalSwitch(transaction, nodeId, logicalSwitchName);
+ return transaction.submit();
+ }
+
+ /**
+ * Delete logical switch from the transaction.
+ *
+ * @param transaction
+ * the transaction
+ * @param nodeId
+ * the node id
+ * @param logicalSwitchName
+ * the logical switch name
+ */
+ public static void deleteLogicalSwitch(final WriteTransaction transaction, final NodeId nodeId,
+ final String logicalSwitchName) {
+ transaction.delete(LogicalDatastoreType.CONFIGURATION, HwvtepSouthboundUtils
+ .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName)));
+ }
+
+ /**
+ * Gets the logical switch.
+ *
+ * @param nodeId
+ * the node id
+ * @param logicalSwitchName
+ * the logical switch name
+ * @return the logical switch
+ */
+ public static LogicalSwitches getLogicalSwitch(DataBroker broker, LogicalDatastoreType datastoreType, NodeId nodeId,
+ String logicalSwitchName) {
+ final InstanceIdentifier<LogicalSwitches> iid = HwvtepSouthboundUtils
+ .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(logicalSwitchName));
+ Optional<LogicalSwitches> optLogicalSwitch = MDSALUtil.read(broker, datastoreType, iid);
+ if (optLogicalSwitch.isPresent()) {
+ return optLogicalSwitch.get();
+ }
+ return null;
+ }
+
+ /**
+ * Get LogicalSwitches for a given hwVtepNodeId.
+ *
+ * @param broker
+ * the broker
+ * @param hwVtepNodeId
+ * Hardware VTEP Node Id
+ * @param vni
+ * virtual network id
+ * @return the logical switches
+ */
+ public static LogicalSwitches getLogicalSwitches(DataBroker broker, String hwVtepNodeId, String vni) {
+ NodeId nodeId = new NodeId(hwVtepNodeId);
+ InstanceIdentifier<LogicalSwitches> logicalSwitchesIdentifier = HwvtepSouthboundUtils
+ .createLogicalSwitchesInstanceIdentifier(nodeId, new HwvtepNodeName(vni));
+
+ Optional<LogicalSwitches> logicalSwitches = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION,
+ logicalSwitchesIdentifier);
+ if (!logicalSwitches.isPresent()) {
+ return null;
+ }
+
+ return logicalSwitches.get();
+ }
+
+ /**
+ * Put physical locators in the transaction.
+ *
+ * @param transaction
+ * the transaction
+ * @param nodeId
+ * the node id
+ * @param lstPhysicalLocator
+ * the lst physical locator
+ */
+ public static void putPhysicalLocators(WriteTransaction transaction, NodeId nodeId,
+ List<HwvtepPhysicalLocatorAugmentation> lstPhysicalLocator) {
+ if (lstPhysicalLocator != null) {
+ for (HwvtepPhysicalLocatorAugmentation phyLocator : lstPhysicalLocator) {
+ putPhysicalLocator(transaction, nodeId, phyLocator);
+ }
+ }
+ }
+
+ /**
+ * Put physical locator in the transaction.
+ *
+ * @param transaction
+ * the transaction
+ * @param nodeId
+ * the node id
+ * @param phyLocator
+ * the phy locator
+ */
+ public static void putPhysicalLocator(final WriteTransaction transaction, final NodeId nodeId,
+ final HwvtepPhysicalLocatorAugmentation phyLocator) {
+ InstanceIdentifier<TerminationPoint> iid = HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(nodeId,
+ phyLocator);
+ TerminationPoint terminationPoint = new TerminationPointBuilder()
+ .setKey(HwvtepSouthboundUtils.getTerminationPointKey(phyLocator))
+ .addAugmentation(HwvtepPhysicalLocatorAugmentation.class, phyLocator).build();
+
+ transaction.put(LogicalDatastoreType.CONFIGURATION, iid, terminationPoint, true);
+ }
+
+ /**
+ * Gets the physical locator.
+ *
+ * @param broker
+ * the broker
+ * @param datastoreType
+ * the datastore type
+ * @param nodeId
+ * the node id
+ * @param phyLocatorIp
+ * the phy locator ip
+ * @return the physical locator
+ */
+ public static HwvtepPhysicalLocatorAugmentation getPhysicalLocator(DataBroker broker,
+ LogicalDatastoreType datastoreType, NodeId nodeId, final IpAddress phyLocatorIp) {
+ HwvtepPhysicalLocatorAugmentation phyLocatorAug = HwvtepSouthboundUtils
+ .createHwvtepPhysicalLocatorAugmentation(String.valueOf(phyLocatorIp.getValue()));
+ InstanceIdentifier<HwvtepPhysicalLocatorAugmentation> iid = HwvtepSouthboundUtils
+ .createPhysicalLocatorInstanceIdentifier(nodeId, phyLocatorAug)
+ .augmentation(HwvtepPhysicalLocatorAugmentation.class);
+ Optional<HwvtepPhysicalLocatorAugmentation> optPhyLocator = MDSALUtil.read(broker, datastoreType, iid);
+ if (optPhyLocator.isPresent()) {
+ return optPhyLocator.get();
+ }
+ return null;
+ }
+
+ /**
+ * Adds the remote ucast macs into config DS.
+ *
+ * @param broker
+ * the broker
+ * @param nodeId
+ * the node id
+ * @param lstRemoteUcastMacs
+ * the lst remote ucast macs
+ * @return the listenable future
+ */
+ public static ListenableFuture<Void> addRemoteUcastMacs(DataBroker broker, NodeId nodeId,
+ List<RemoteUcastMacs> lstRemoteUcastMacs) {
+ WriteTransaction transaction = broker.newWriteOnlyTransaction();
+ putRemoteUcastMacs(transaction, nodeId, lstRemoteUcastMacs);
+ return transaction.submit();
+ }
+
+ /**
+ * Put remote ucast macs in the transaction.
+ *
+ * @param transaction
+ * the transaction
+ * @param nodeId
+ * the node id
+ * @param lstRemoteUcastMacs
+ * the lst remote ucast macs
+ */
+ public static void putRemoteUcastMacs(final WriteTransaction transaction, final NodeId nodeId,
+ final List<RemoteUcastMacs> lstRemoteUcastMacs) {
+ if (lstRemoteUcastMacs != null && !lstRemoteUcastMacs.isEmpty()) {
+ for (RemoteUcastMacs remoteUcastMac : lstRemoteUcastMacs) {
+ putRemoteUcastMac(transaction, nodeId, remoteUcastMac);
+ }
+ }
+ }
+
+ /**
+ * Put remote ucast mac in the transaction.
+ *
+ * @param transaction
+ * the transaction
+ * @param nodeId
+ * the node id
+ * @param remoteUcastMac
+ * the remote ucast mac
+ */
+ public static void putRemoteUcastMac(final WriteTransaction transaction, final NodeId nodeId,
+ RemoteUcastMacs remoteUcastMac) {
+ InstanceIdentifier<RemoteUcastMacs> iid = HwvtepSouthboundUtils.createInstanceIdentifier(nodeId)
+ .augmentation(HwvtepGlobalAugmentation.class).child(RemoteUcastMacs.class,
+ new RemoteUcastMacsKey(remoteUcastMac.getLogicalSwitchRef(), remoteUcastMac.getMacEntryKey()));
+ transaction.put(LogicalDatastoreType.CONFIGURATION, iid, remoteUcastMac, true);
+ }
+
+ /**
+ * Delete remote ucast mac from the config DS.
+ *
+ * @param broker
+ * the broker
+ * @param nodeId
+ * the node id
+ * @param mac
+ * the mac
+ * @return the listenable future
+ */
+ public static ListenableFuture<Void> deleteRemoteUcastMac(DataBroker broker, NodeId nodeId,
+ String logicalSwitchName, MacAddress mac) {
+ WriteTransaction transaction = broker.newWriteOnlyTransaction();
+ deleteRemoteUcastMac(transaction, nodeId, logicalSwitchName, mac);
+ return transaction.submit();
+ }
+
+ /**
+ * Delete remote ucast macs from the config DS.
+ *
+ * @param broker
+ * the broker
+ * @param nodeId
+ * the node id
+ * @param lstMac
+ * the lst mac
+ * @return the listenable future
+ */
+ public static ListenableFuture<Void> deleteRemoteUcastMacs(DataBroker broker, NodeId nodeId,
+ String logicalSwitchName, List<MacAddress> lstMac) {
+ WriteTransaction transaction = broker.newWriteOnlyTransaction();
+ deleteRemoteUcastMacs(transaction, nodeId, logicalSwitchName, lstMac);
+ return transaction.submit();
+ }
+
+ /**
+ * Delete remote ucast macs from the transaction.
+ *
+ * @param transaction
+ * the transaction
+ * @param nodeId
+ * the node id
+ * @param lstMac
+ * the lst mac
+ */
+ public static void deleteRemoteUcastMacs(final WriteTransaction transaction, final NodeId nodeId,
+ String logicalSwitchName, final List<MacAddress> lstMac) {
+ if (lstMac != null && !lstMac.isEmpty()) {
+ for (MacAddress mac : lstMac) {
+ deleteRemoteUcastMac(transaction, nodeId, logicalSwitchName, mac);
+ }
+ }
+ }
+
+ /**
+ * Delete remote ucast mac from the transaction.
+ *
+ * @param transaction
+ * the transaction
+ * @param nodeId
+ * the node id
+ * @param mac
+ * the mac
+ */
+ public static void deleteRemoteUcastMac(final WriteTransaction transaction, final NodeId nodeId,
+ String logialSwitchName, final MacAddress mac) {
+ transaction.delete(LogicalDatastoreType.CONFIGURATION,
+ HwvtepSouthboundUtils.createRemoteUcastMacsInstanceIdentifier(nodeId, logialSwitchName, mac));
+ }
+
+ /**
+ * Adds the remote mcast macs into config DS.
+ *
+ * @param broker
+ * the broker
+ * @param nodeId
+ * the node id
+ * @param lstRemoteMcastMacs
+ * the lst remote mcast macs
+ * @return the listenable future
+ */
+ public static ListenableFuture<Void> addRemoteMcastMacs(DataBroker broker, NodeId nodeId,
+ List<RemoteMcastMacs> lstRemoteMcastMacs) {
+ WriteTransaction transaction = broker.newWriteOnlyTransaction();
+ putRemoteMcastMacs(transaction, nodeId, lstRemoteMcastMacs);
+ return transaction.submit();
+ }
+
+ /**
+ * Put remote mcast macs in the transaction.
+ *
+ * @param transaction
+ * the transaction
+ * @param nodeId
+ * the node id
+ * @param lstRemoteMcastMacs
+ * the lst remote mcast macs
+ */
+ public static void putRemoteMcastMacs(final WriteTransaction transaction, final NodeId nodeId,
+ final List<RemoteMcastMacs> lstRemoteMcastMacs) {
+ if (lstRemoteMcastMacs != null && !lstRemoteMcastMacs.isEmpty()) {
+ for (RemoteMcastMacs remoteMcastMac : lstRemoteMcastMacs) {
+ putRemoteMcastMac(transaction, nodeId, remoteMcastMac);
+ }
+ }
+ }
+
+ /**
+ * Put remote mcast mac in the transaction.
+ *
+ * @param transaction
+ * the transaction
+ * @param nodeId
+ * the node id
+ * @param remoteMcastMac
+ * the remote mcast mac
+ */
+ public static void putRemoteMcastMac(final WriteTransaction transaction, final NodeId nodeId,
+ RemoteMcastMacs remoteMcastMac) {
+ InstanceIdentifier<RemoteMcastMacs> iid = HwvtepSouthboundUtils.createRemoteMcastMacsInstanceIdentifier(nodeId,
+ remoteMcastMac.getKey());
+ transaction.put(LogicalDatastoreType.CONFIGURATION, iid, remoteMcastMac, true);
+ }
+
+ public static void putRemoteMcastMac(final WriteTransaction transaction,LogicalDatastoreType logicalDatastoreType,
+ final NodeId nodeId,
+ RemoteMcastMacs remoteMcastMac) {
+ InstanceIdentifier<RemoteMcastMacs> iid = HwvtepSouthboundUtils.createRemoteMcastMacsInstanceIdentifier(nodeId,
+ remoteMcastMac.getKey());
+ transaction.put(logicalDatastoreType, iid, remoteMcastMac, true);
+ }
+ /**
+ * Gets the remote mcast mac.
+ *
+ * @param broker
+ * the broker
+ * @param datastoreType
+ * the datastore type
+ * @param nodeId
+ * the node id
+ * @param remoteMcastMacsKey
+ * the remote mcast macs key
+ * @return the remote mcast mac
+ */
+ public static RemoteMcastMacs getRemoteMcastMac(DataBroker broker, LogicalDatastoreType datastoreType,
+ NodeId nodeId, RemoteMcastMacsKey remoteMcastMacsKey) {
+ final InstanceIdentifier<RemoteMcastMacs> iid = HwvtepSouthboundUtils
+ .createRemoteMcastMacsInstanceIdentifier(nodeId, remoteMcastMacsKey);
+ Optional<RemoteMcastMacs> optRemoteMcastMac = MDSALUtil.read(broker, datastoreType, iid);
+ if (optRemoteMcastMac.isPresent()) {
+ return optRemoteMcastMac.get();
+ }
+ return null;
+ }
+
+ /**
+ * Delete remote mcast mac from config DS.
+ *
+ * @param broker
+ * the broker
+ * @param nodeId
+ * the node id
+ * @param remoteMcastMacsKey
+ * the remote mcast macs key
+ * @return the listenable future
+ */
+ public static ListenableFuture<Void> deleteRemoteMcastMac(DataBroker broker, NodeId nodeId,
+ RemoteMcastMacsKey remoteMcastMacsKey) {
+ WriteTransaction transaction = broker.newWriteOnlyTransaction();
+ deleteRemoteMcastMac(transaction, nodeId, remoteMcastMacsKey);
+ return transaction.submit();
+ }
+
+ /**
+ * Delete remote mcast macs from config DS.
+ *
+ * @param broker
+ * the broker
+ * @param nodeId
+ * the node id
+ * @param lstRemoteMcastMacsKey
+ * the lst remote mcast macs key
+ * @return the listenable future
+ */
+ public static ListenableFuture<Void> deleteRemoteMcastMacs(DataBroker broker, NodeId nodeId,
+ List<RemoteMcastMacsKey> lstRemoteMcastMacsKey) {
+ WriteTransaction transaction = broker.newWriteOnlyTransaction();
+ deleteRemoteMcastMacs(transaction, nodeId, lstRemoteMcastMacsKey);
+ return transaction.submit();
+ }
+
+ /**
+ * Delete remote mcast macs from the transaction.
+ *
+ * @param transaction
+ * the transaction
+ * @param nodeId
+ * the node id
+ * @param lstRemoteMcastMacsKey
+ * the lst remote mcast macs key
+ */
+ public static void deleteRemoteMcastMacs(final WriteTransaction transaction, final NodeId nodeId,
+ final List<RemoteMcastMacsKey> lstRemoteMcastMacsKey) {
+ if (lstRemoteMcastMacsKey != null && !lstRemoteMcastMacsKey.isEmpty()) {
+ for (RemoteMcastMacsKey mac : lstRemoteMcastMacsKey) {
+ deleteRemoteMcastMac(transaction, nodeId, mac);
+ }
+ }
+ }
+
+ /**
+ * Delete remote mcast mac from the transaction.
+ *
+ * @param transaction
+ * the transaction
+ * @param nodeId
+ * the node id
+ * @param remoteMcastMacsKey
+ * the remote mcast macs key
+ */
+ public static void deleteRemoteMcastMac(final WriteTransaction transaction, final NodeId nodeId,
+ final RemoteMcastMacsKey remoteMcastMacsKey) {
+ transaction.delete(LogicalDatastoreType.CONFIGURATION,
+ HwvtepSouthboundUtils.createRemoteMcastMacsInstanceIdentifier(nodeId, remoteMcastMacsKey));
+ }
+
+ /**
+ * Merge vlan bindings in the transaction.
+ *
+ * @param transaction
+ * the transaction
+ * @param nodeId
+ * the node id
+ * @param phySwitchName
+ * the phy switch name
+ * @param phyPortName
+ * the phy port name
+ * @param vlanBindings
+ * the vlan bindings
+ */
+ public static void mergeVlanBindings(final WriteTransaction transaction, final NodeId nodeId,
+ final String phySwitchName, final String phyPortName, final List<VlanBindings> vlanBindings) {
+ NodeId physicalSwitchNodeId = HwvtepSouthboundUtils.createManagedNodeId(nodeId, phySwitchName);
+ mergeVlanBindings(transaction, physicalSwitchNodeId, phyPortName, vlanBindings);
+ }
+
+ /**
+ * Merge vlan bindings in the transaction.
+ *
+ * @param transaction
+ * the transaction
+ * @param physicalSwitchNodeId
+ * the physical switch node id
+ * @param phyPortName
+ * the phy port name
+ * @param vlanBindings
+ * the vlan bindings
+ */
+ public static void mergeVlanBindings(final WriteTransaction transaction, final NodeId physicalSwitchNodeId,
+ final String phyPortName, final List<VlanBindings> vlanBindings) {
+ HwvtepPhysicalPortAugmentation phyPortAug = new HwvtepPhysicalPortAugmentationBuilder()
+ .setHwvtepNodeName(new HwvtepNodeName(phyPortName)).setVlanBindings(vlanBindings).build();
+
+ final InstanceIdentifier<HwvtepPhysicalPortAugmentation> iid = HwvtepSouthboundUtils
+ .createPhysicalPortInstanceIdentifier(physicalSwitchNodeId, phyPortName);
+ transaction.merge(LogicalDatastoreType.CONFIGURATION, iid, phyPortAug, true);
+ }
+
+ /**
+ * Delete vlan binding from transaction.
+ *
+ * @param transaction
+ * the transaction
+ * @param physicalSwitchNodeId
+ * the physical switch node id
+ * @param phyPortName
+ * the phy port name
+ * @param vlanId
+ * the vlan id
+ */
+ public static void deleteVlanBinding(WriteTransaction transaction, NodeId physicalSwitchNodeId, String phyPortName,
+ Integer vlanId) {
+ InstanceIdentifier<VlanBindings> iid = HwvtepSouthboundUtils
+ .createVlanBindingInstanceIdentifier(physicalSwitchNodeId, phyPortName, vlanId);
+ transaction.delete(LogicalDatastoreType.CONFIGURATION, iid);
+ }
+
+ /**
+ * Gets the hw vtep node.
+ *
+ * @param dataBroker
+ * the data broker
+ * @param datastoreType
+ * the datastore type
+ * @param nodeId
+ * the node id
+ * @return the hw vtep node
+ */
+ public static Node getHwVtepNode(DataBroker dataBroker, LogicalDatastoreType datastoreType, NodeId nodeId) {
+ Optional<Node> optNode = MDSALUtil.read(dataBroker, datastoreType,
+ HwvtepSouthboundUtils.createInstanceIdentifier(nodeId));
+ if (optNode.isPresent()) {
+ return optNode.get();
+ }
+ return null;
+ }
+
+ /**
+ * Installs a list of Mac Addresses as remote Ucast address in an external
+ * device using the hwvtep-southbound.
+ *
+ * @param deviceNodeId
+ * NodeId if the ExternalDevice where the macs must be installed
+ * in.
+ * @param macAddresses
+ * List of Mac addresses to be installed in the external device.
+ * @param logicalSwitchName
+ * the logical switch name
+ * @param remoteVtepIp
+ * VTEP's IP in this CSS used for the tunnel with external
+ * device.
+ */
+ public static ListenableFuture<Void> installUcastMacs(DataBroker broker,
+ String deviceNodeId, List<PhysAddress> macAddresses,
+ String logicalSwitchName, IpAddress remoteVtepIp) {
+ NodeId nodeId = new NodeId(deviceNodeId);
+ HwvtepPhysicalLocatorAugmentation phyLocatorAug = HwvtepSouthboundUtils
+ .createHwvtepPhysicalLocatorAugmentation(String.valueOf(remoteVtepIp.getValue()));
+ List<RemoteUcastMacs> macs = new ArrayList<RemoteUcastMacs>();
+ for (PhysAddress mac : macAddresses) {
+ // TODO: Query ARP cache to get IP address corresponding to
+ // the MAC
+ IpAddress ipAddress = null;
+ macs.add(HwvtepSouthboundUtils.createRemoteUcastMac(nodeId, mac.getValue(), ipAddress, logicalSwitchName,
+ phyLocatorAug));
+ }
+ return HwvtepUtils.addRemoteUcastMacs(broker, nodeId, macs);
+ }
+
+}
--- /dev/null
+module odl-mdsalutil {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:mdsalutil:api";
+ prefix "odl-mdsal";
+
+ import config { prefix config; revision-date 2013-04-05; }
+
+ description
+ "Service definition for MD-SAL Util.";
+
+ revision "2015-04-10" {
+ description
+ "Initial revision";
+ }
+
+ identity odl-mdsalutil {
+ base "config:service-type";
+ config:java-class "org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager";
+ }
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>mdsalutil-impl</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.model</groupId>
+ <artifactId>model-flow-base</artifactId>
+ <version>${openflowplugin.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>liblldp</artifactId>
+ <version>${liblldp.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.model</groupId>
+ <artifactId>model-flow-service</artifactId>
+ <version>${openflowplugin.version}</version>
+ </dependency>
+ <!-- TEST Dependencies -->
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <version>${mdsal.version}</version>
+ <scope>test</scope>
+ <type>test-jar</type>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mdsalutil-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <argLine>-XX:-UseSplitVerifier</argLine>
+ </configuration>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright (c) 2015 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:mdsalutil:api?module=odl-mdsalutil&revision=2015-04-10</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:mdsalutil:impl?module=mdsalutil-impl&revision=2015-04-03</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</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:mdsalutil:impl">prefix:mdsalutil-impl</type>
+ <name>mdsalutil-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>
+ </module>
+ </modules>
+ <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <service>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:mdsalutil:api">prefix:odl-mdsalutil</type>
+ <instance>
+ <name>mdsalutil-service</name>
+ <provider>/modules/module[type='mdsalutil-impl'][name='mdsalutil-default']</provider>
+ </instance>
+ </service>
+ </services>
+ </data>
+ </configuration>
+</snapshot>
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.vpnservice.mdsalutil.internal;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+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.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+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.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.opendaylight.vpnservice.mdsalutil.*;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.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.controller.md.sal.common.api.data.OptimisticLockFailedException;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
+public class MDSALManager implements AutoCloseable {
+
+ private static final Logger s_logger = LoggerFactory.getLogger(MDSALManager.class);
+
+ private DataBroker m_dataBroker;
+
+ private PacketProcessingService m_packetProcessingService;
+ private ListenerRegistration<DataChangeListener> groupListenerRegistration;
+ private ListenerRegistration<DataChangeListener> flowListenerRegistration;
+ private ConcurrentMap<FlowInfoKey, Runnable> flowMap = new ConcurrentHashMap<FlowInfoKey, Runnable>();
+ private ConcurrentMap<GroupInfoKey, Runnable> groupMap = new ConcurrentHashMap<GroupInfoKey, Runnable> ();
+ private ExecutorService executorService = Executors.newSingleThreadExecutor();
+
+ /**
+ * Writes the flows and Groups to the MD SAL DataStore
+ * which will be sent to the openflowplugin for installing flows/groups on the switch.
+ * Other modules of VPN service that wants to install flows / groups on the switch
+ * uses this utility
+ *
+ * @param db - dataBroker reference
+ * @param pktProcService- PacketProcessingService for sending the packet outs
+ */
+ public MDSALManager(final DataBroker db, PacketProcessingService pktProcService) {
+ m_dataBroker = db;
+ m_packetProcessingService = pktProcService;
+ registerListener(db);
+ s_logger.info( "MDSAL Manager Initialized ") ;
+ }
+
+ @Override
+ public void close() throws Exception {
+ groupListenerRegistration.close();
+ flowListenerRegistration.close();
+ s_logger.info("MDSAL Manager Closed");
+ }
+
+ private void registerListener(DataBroker db) {
+ try {
+ flowListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, getWildCardFlowPath(),
+ new FlowListener(),
+ DataChangeScope.SUBTREE);
+ groupListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, getWildCardGroupPath(),
+ new GroupListener(),
+ DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ s_logger.error("GroupEventHandler: DataChange listener registration fail!", e);
+ throw new IllegalStateException("GroupEventHandler: registration Listener failed.", e);
+ }
+ }
+
+ private InstanceIdentifier<Group> getWildCardGroupPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class).augmentation(FlowCapableNode.class).child(Group.class);
+ }
+
+ private InstanceIdentifier<Flow> getWildCardFlowPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class).augmentation(FlowCapableNode.class).child(Table.class).child(Flow.class);
+ }
+
+ public void installFlow(FlowEntity flowEntity) {
+
+ try {
+ s_logger.trace("InstallFlow for flowEntity {} ", flowEntity);
+
+ if (flowEntity.getCookie() == null) {
+ flowEntity.setCookie(new BigInteger("0110000", 16));
+ }
+
+ FlowKey flowKey = new FlowKey( new FlowId(flowEntity.getFlowId()) );
+
+ FlowBuilder flowbld = flowEntity.getFlowBuilder();
+
+ Node nodeDpn = buildDpnNode(flowEntity.getDpnId());
+ InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
+ .child(Table.class, new TableKey(flowEntity.getTableId())).child(Flow.class,flowKey).build();
+
+ WriteTransaction modification = m_dataBroker.newWriteOnlyTransaction();
+
+ modification.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flowbld.build(),true );
+
+ CheckedFuture<Void,TransactionCommitFailedException> submitFuture = modification.submit();
+
+ Futures.addCallback(submitFuture, new FutureCallback<Void>() {
+
+ @Override
+ public void onSuccess(final Void result) {
+ // Commited successfully
+ s_logger.debug( "Install Flow -- Committedsuccessfully ") ;
+ }
+
+ @Override
+ public void onFailure(final Throwable t) {
+ // Transaction failed
+
+ if(t instanceof OptimisticLockFailedException) {
+ // Failed because of concurrent transaction modifying same data
+ s_logger.error( "Install Flow -- Failed because of concurrent transaction modifying same data ") ;
+ } else {
+ // Some other type of TransactionCommitFailedException
+ s_logger.error( "Install Flow -- Some other type of TransactionCommitFailedException " + t) ;
+ }
+ }
+ });
+ } catch (Exception e) {
+ s_logger.error("Could not install flow: {}", flowEntity, e);
+ }
+ }
+
+ public CheckedFuture<Void,TransactionCommitFailedException> installFlow(BigInteger dpId, Flow flow) {
+ FlowKey flowKey = new FlowKey( new FlowId(flow.getId()) );
+ 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();
+ WriteTransaction modification = m_dataBroker.newWriteOnlyTransaction();
+ modification.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flow, true);
+ return modification.submit();
+ }
+
+ public void installGroup(GroupEntity groupEntity) {
+ try {
+ Group group = groupEntity.getGroupBuilder().build();
+
+ Node nodeDpn = buildDpnNode(groupEntity.getDpnId());
+
+ InstanceIdentifier<Group> groupInstanceId = InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
+ .child(Group.class, new GroupKey(new GroupId(groupEntity.getGroupId()))).build();
+
+ WriteTransaction modification = m_dataBroker.newWriteOnlyTransaction();
+
+ modification.put(LogicalDatastoreType.CONFIGURATION, groupInstanceId, group, true);
+
+ CheckedFuture<Void,TransactionCommitFailedException> submitFuture = modification.submit();
+
+ Futures.addCallback(submitFuture, new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(final Void result) {
+ // Commited successfully
+ s_logger.debug( "Install Group -- Committedsuccessfully ") ;
+ }
+
+ @Override
+ public void onFailure(final Throwable t) {
+ // Transaction failed
+
+ if(t instanceof OptimisticLockFailedException) {
+ // Failed because of concurrent transaction modifying same data
+ s_logger.error( "Install Group -- Failed because of concurrent transaction modifying same data ") ;
+ } else {
+ // Some other type of TransactionCommitFailedException
+ s_logger.error( "Install Group -- Some other type of TransactionCommitFailedException " + t) ;
+ }
+ }
+ });
+ } catch (Exception e) {
+ s_logger.error("Could not install Group: {}", groupEntity, e);
+ throw e;
+ }
+ }
+
+ public void removeFlow(FlowEntity flowEntity) {
+ try {
+ s_logger.debug("Remove flow {}",flowEntity);
+ Node nodeDpn = buildDpnNode(flowEntity.getDpnId());
+ FlowKey flowKey = new FlowKey(new FlowId(flowEntity.getFlowId()));
+ InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
+ .child(Table.class, new TableKey(flowEntity.getTableId())).child(Flow.class, flowKey).build();
+
+
+ WriteTransaction modification = m_dataBroker.newWriteOnlyTransaction();
+ modification.delete(LogicalDatastoreType.CONFIGURATION,flowInstanceId);
+
+ CheckedFuture<Void,TransactionCommitFailedException> submitFuture = modification.submit();
+
+ Futures.addCallback(submitFuture, new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(final Void result) {
+ // Commited successfully
+ s_logger.debug( "Delete Flow -- Committedsuccessfully ") ;
+ }
+
+ @Override
+ public void onFailure(final Throwable t) {
+ // Transaction failed
+ if(t instanceof OptimisticLockFailedException) {
+ // Failed because of concurrent transaction modifying same data
+ s_logger.error( "Delete Flow -- Failed because of concurrent transaction modifying same data ") ;
+ } else {
+ // Some other type of TransactionCommitFailedException
+ s_logger.error( "Delete Flow -- Some other type of TransactionCommitFailedException " + t) ;
+ }
+ }
+
+ });
+ } catch (Exception e) {
+ s_logger.error("Could not remove Flow: {}", flowEntity, e);
+ }
+ }
+
+ public CheckedFuture<Void,TransactionCommitFailedException> removeFlowNew(BigInteger dpnId, Flow flowEntity) {
+ s_logger.debug("Remove flow {}",flowEntity);
+ Node nodeDpn = buildDpnNode(dpnId);
+ //FlowKey flowKey = new FlowKey(new FlowId(flowEntity.getId()));
+ FlowKey flowKey = new FlowKey(flowEntity.getId());
+ InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
+ .child(Table.class, new TableKey(flowEntity.getTableId())).child(Flow.class, flowKey).build();
+ WriteTransaction modification = m_dataBroker.newWriteOnlyTransaction();
+ modification.delete(LogicalDatastoreType.CONFIGURATION,flowInstanceId );
+ return modification.submit();
+ }
+
+ public void removeGroup(GroupEntity groupEntity) {
+ try {
+ Node nodeDpn = buildDpnNode(groupEntity.getDpnId());
+ InstanceIdentifier<Group> groupInstanceId = InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
+ .child(Group.class, new GroupKey(new GroupId(groupEntity.getGroupId()))).build();
+
+ WriteTransaction modification = m_dataBroker.newWriteOnlyTransaction();
+
+ modification.delete(LogicalDatastoreType.CONFIGURATION,groupInstanceId );
+
+ CheckedFuture<Void,TransactionCommitFailedException> submitFuture = modification.submit();
+
+ Futures.addCallback(submitFuture, new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(final Void result) {
+ // Commited successfully
+ s_logger.debug( "Install Group -- Committedsuccessfully ") ;
+ }
+
+ @Override
+ public void onFailure(final Throwable t) {
+ // Transaction failed
+ if(t instanceof OptimisticLockFailedException) {
+ // Failed because of concurrent transaction modifying same data
+ s_logger.error( "Install Group -- Failed because of concurrent transaction modifying same data ") ;
+ } else {
+ // Some other type of TransactionCommitFailedException
+ s_logger.error( "Install Group -- Some other type of TransactionCommitFailedException " + t) ;
+ }
+ }
+ });
+ } catch (Exception e) {
+ s_logger.error("Could not remove Group: {}", groupEntity, e);
+ }
+ }
+
+ public void modifyGroup(GroupEntity groupEntity) {
+
+ installGroup(groupEntity);
+ }
+
+ public void sendPacketOut(BigInteger dpnId, int groupId, byte[] payload) {
+
+ List<ActionInfo> actionInfos = new ArrayList<ActionInfo>();
+ actionInfos.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId) }));
+
+ sendPacketOutWithActions(dpnId, groupId, payload, actionInfos);
+ }
+
+ public void sendPacketOutWithActions(BigInteger dpnId, long groupId, byte[] payload, List<ActionInfo> actionInfos) {
+
+ m_packetProcessingService.transmitPacket(MDSALUtil.getPacketOut(actionInfos, payload, dpnId,
+ getNodeConnRef("openflow:" + dpnId, "0xfffffffd")));
+ }
+
+ public void sendARPPacketOutWithActions(BigInteger dpnId, byte[] payload, List<ActionInfo> actions) {
+ m_packetProcessingService.transmitPacket(MDSALUtil.getPacketOut(actions, payload, dpnId,
+ getNodeConnRef("openflow:" + dpnId, "0xfffffffd")));
+ }
+
+ public InstanceIdentifier<Node> nodeToInstanceId(Node node) {
+ return InstanceIdentifier.builder(Nodes.class).child(Node.class, node.getKey()).toInstance();
+ }
+
+ private static NodeConnectorRef getNodeConnRef(final String nodeId, final String port) {
+ StringBuilder _stringBuilder = new StringBuilder(nodeId);
+ StringBuilder _append = _stringBuilder.append(":");
+ StringBuilder sBuild = _append.append(port);
+ String _string = sBuild.toString();
+ NodeConnectorId _nodeConnectorId = new NodeConnectorId(_string);
+ NodeConnectorKey _nodeConnectorKey = new NodeConnectorKey(_nodeConnectorId);
+ NodeConnectorKey nConKey = _nodeConnectorKey;
+ InstanceIdentifierBuilder<Nodes> _builder = InstanceIdentifier.<Nodes> builder(Nodes.class);
+ NodeId _nodeId = new NodeId(nodeId);
+ NodeKey _nodeKey = new NodeKey(_nodeId);
+ InstanceIdentifierBuilder<Node> _child = _builder.<Node, NodeKey> child(Node.class, _nodeKey);
+ InstanceIdentifierBuilder<NodeConnector> _child_1 = _child.<NodeConnector, NodeConnectorKey> child(
+ NodeConnector.class, nConKey);
+ InstanceIdentifier<NodeConnector> path = _child_1.toInstance();
+ NodeConnectorRef _nodeConnectorRef = new NodeConnectorRef(path);
+ return _nodeConnectorRef;
+ }
+
+ private Node buildDpnNode(BigInteger dpnId) {
+ NodeId nodeId = new NodeId("openflow:" + dpnId);
+ Node nodeDpn = new NodeBuilder().setId(nodeId).setKey(new NodeKey(nodeId)).build();
+
+ 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){}
+ }
+ }
+ }
+
+ public void syncSetUpGroup(BigInteger dpId, Group group, long delayTime, boolean isRemove) {
+ s_logger.trace("syncSetUpGroup for group {} ", group);
+ Node nodeDpn = buildDpnNode(dpId);
+ long groupId = group.getGroupId().getValue();
+ 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){}
+ }
+ }
+ }
+
+ class GroupListener extends AbstractDataChangeListener<Group> {
+
+ public GroupListener() {
+ super(Group.class);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Group> identifier, Group del) {
+ BigInteger dpId = getDpnFromString(identifier.firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+ executeNotifyTaskIfRequired(dpId, del);
+ }
+
+ private void executeNotifyTaskIfRequired(BigInteger dpId, Group group) {
+ GroupInfoKey groupKey = new GroupInfoKey(dpId, group.getGroupId().getValue());
+ Runnable notifyTask = groupMap.remove(groupKey);
+ if (notifyTask == null) {
+ return;
+ }
+ executorService.execute(notifyTask);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Group> identifier, Group original, Group update) {
+ BigInteger dpId = getDpnFromString(identifier.firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+ executeNotifyTaskIfRequired(dpId, update);
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Group> identifier, Group add) {
+ BigInteger dpId = getDpnFromString(identifier.firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+ executeNotifyTaskIfRequired(dpId, add);
+ }
+ }
+
+ class FlowListener extends AbstractDataChangeListener<Flow> {
+
+ public FlowListener() {
+ super(Flow.class);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Flow> identifier, Flow del) {
+ BigInteger dpId = getDpnFromString(identifier.firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+ notifyTaskIfRequired(dpId, del);
+ }
+
+ private void notifyTaskIfRequired(BigInteger dpId, Flow flow) {
+ FlowInfoKey flowKey = new FlowInfoKey(dpId, flow.getTableId(), flow.getMatch(), flow.getId().getValue());
+ Runnable notifyTask = flowMap.remove(flowKey);
+ if (notifyTask == null) {
+ return;
+ }
+ executorService.execute(notifyTask);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Flow> identifier, Flow original, Flow update) {
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Flow> identifier, Flow add) {
+ BigInteger dpId = getDpnFromString(identifier.firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+ notifyTaskIfRequired(dpId, add);
+ }
+ }
+
+ private BigInteger getDpnFromString(String dpnString) {
+ String[] split = dpnString.split(":");
+ return new BigInteger(split[1]);
+ }
+
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.mdsalutil.internal;
+
+import java.math.BigInteger;
+
+import java.util.List;
+
+import com.google.common.util.concurrent.CheckedFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
+import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
+import org.opendaylight.vpnservice.mdsalutil.GroupEntity;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+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) {
+
+ s_logger.info( " Session Initiated for MD SAL Util Provider") ;
+
+ try {
+ final DataBroker dataBroker;
+ final PacketProcessingService packetProcessingService;
+ dataBroker = session.getSALService(DataBroker.class);
+ packetProcessingService = session.getRpcService(PacketProcessingService.class);
+ mdSalMgr = new MDSALManager( dataBroker, packetProcessingService) ;
+ }catch( Exception e) {
+ s_logger.error( "Error initializing MD SAL Util Services " + e );
+ }
+ }
+
+
+ @Override
+ public void close() throws Exception {
+ mdSalMgr.close();
+ s_logger.info("MDSAL Manager Closed");
+ }
+
+
+ @Override
+ public void installFlow(FlowEntity flowEntity) {
+ mdSalMgr.installFlow(flowEntity);
+ }
+
+ @Override
+ public CheckedFuture<Void, TransactionCommitFailedException> installFlow(BigInteger dpId, Flow flowEntity) {
+ return mdSalMgr.installFlow(dpId, flowEntity);
+ }
+
+ @Override
+ public CheckedFuture<Void, TransactionCommitFailedException> installFlow(BigInteger dpId, FlowEntity flowEntity) {
+ return mdSalMgr.installFlow(dpId, flowEntity.getFlowBuilder().build());
+ }
+
+ @Override
+ public CheckedFuture<Void, TransactionCommitFailedException> removeFlow(BigInteger dpId, Flow flowEntity) {
+ return mdSalMgr.removeFlowNew(dpId, flowEntity);
+ }
+
+ @Override
+ public CheckedFuture<Void, TransactionCommitFailedException> removeFlow(BigInteger dpId, FlowEntity flowEntity) {
+ return mdSalMgr.removeFlowNew(dpId, flowEntity.getFlowBuilder().build());
+ }
+
+ @Override
+ public void removeFlow(FlowEntity flowEntity) {
+ mdSalMgr.removeFlow(flowEntity);
+ }
+
+ @Override
+ public void installGroup(GroupEntity groupEntity) {
+ mdSalMgr.installGroup(groupEntity);
+ }
+
+
+ @Override
+ public void modifyGroup(GroupEntity groupEntity) {
+ mdSalMgr.modifyGroup(groupEntity);
+ }
+
+
+ @Override
+ public void removeGroup(GroupEntity groupEntity) {
+ mdSalMgr.removeGroup(groupEntity);
+ }
+
+
+ @Override
+ public void sendPacketOut(BigInteger dpnId, int groupId, byte[] payload) {
+ mdSalMgr.sendPacketOut(dpnId, groupId, payload);
+ }
+
+
+ @Override
+ public void sendPacketOutWithActions(BigInteger dpnId, long groupId,
+ byte[] payload, List<ActionInfo> actionInfos) {
+ mdSalMgr.sendPacketOutWithActions(dpnId, groupId, payload, actionInfos);
+ }
+
+
+ @Override
+ public void sendARPPacketOutWithActions(BigInteger dpnId, byte[] payload,
+ List<ActionInfo> action_info) {
+ mdSalMgr.sendARPPacketOutWithActions(dpnId, payload, action_info);
+ }
+
+ @Override
+ public void syncRemoveFlow(FlowEntity flowEntity, long delayTime) {
+ mdSalMgr.syncSetUpFlow(flowEntity, delayTime, true);
+ }
+
+ @Override
+ public void syncInstallFlow(FlowEntity flowEntity, long delayTime) {
+ mdSalMgr.syncSetUpFlow(flowEntity, delayTime, false);
+ }
+
+ @Override
+ public void syncInstallGroup(GroupEntity groupEntity, long delayTime) {
+ mdSalMgr.syncSetUpGroup(groupEntity, delayTime, false);
+ }
+
+ @Override
+ public void syncInstallGroup(BigInteger dpId, Group group, long delayTime) {
+ mdSalMgr.syncSetUpGroup(dpId, group, delayTime, false);
+ }
+
+ @Override
+ public void syncRemoveGroup(GroupEntity groupEntity) {
+ mdSalMgr.syncSetUpGroup(groupEntity, FIXED_DELAY_IN_MILLISECONDS, true);
+ }
+
+ @Override
+ public void syncRemoveGroup(BigInteger dpId, Group group) {
+ mdSalMgr.syncSetUpGroup(dpId, group, 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();
+ }
+ }
+
+}
--- /dev/null
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsalutil.impl.rev150403;
+
+import org.opendaylight.vpnservice.mdsalutil.internal.MDSALUtilProvider;
+
+public class MdsaluttilimplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsalutil.impl.rev150403.AbstractMdsaluttilimplModule {
+ public MdsaluttilimplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public MdsaluttilimplModule(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.mdsalutil.impl.rev150403.MdsaluttilimplModule 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() {
+ // TODO:implement
+// Can use the following to get a handle to data broker
+
+ MDSALUtilProvider mdsalUtilProvider = new MDSALUtilProvider();
+ getBrokerDependency().registerConsumer(mdsalUtilProvider);
+ //DataBroker dataBrokerService = getDataBrokerDependency();
+ //mdsalUtilMgr.setDataProvider(dataBrokerService);
+ return mdsalUtilProvider ;
+ }
+
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: mdsalutil-impl yang module local name: mdsalutil-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Fri Apr 03 21:19:12 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.mdsalutil.impl.rev150403;
+public class MdsaluttilimplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsalutil.impl.rev150403.AbstractMdsaluttilimplModuleFactory {
+
+}
--- /dev/null
+module mdsalutil-impl {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:mdsalutil:impl";
+ prefix "mdsalutil-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 odl-mdsalutil { prefix odl-mdsal; revision-date 2015-04-10;}
+
+ description
+ "Service definition for mdsal project";
+
+ revision "2015-04-03" {
+ description
+ "Initial revision";
+ }
+
+ identity mdsalutil-impl {
+ base config:module-type;
+ config:provided-service odl-mdsal:odl-mdsalutil;
+ config:java-name-prefix Mdsaluttilimpl;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case mdsalutil-impl {
+ when "/config:modules/config:module/config:type = 'mdsalutil-impl'";
+ container broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-broker-osgi-registry;
+ }
+ }
+ }
+
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.test;
+
+import java.util.Collection;
+
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import com.google.common.base.Preconditions;
+
+public abstract class AbstractMockForwardingRulesManager<D extends DataObject> implements DataTreeChangeListener<D> {
+
+ public AbstractMockForwardingRulesManager() {
+ // Do Nothing
+ }
+
+
+ public void onDataTreeChanged(Collection<DataTreeModification<D>> changes) {
+ // TODO Auto-generated method stub
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.test;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Collections;
+import java.util.concurrent.ExecutionException;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+import org.mockito.runners.MockitoJUnitRunner;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+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.BucketInfo;
+import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
+import org.opendaylight.vpnservice.mdsalutil.InstructionType;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.vpnservice.mdsalutil.internal.MDSALManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+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.group.types.rev131018.GroupTypes;
+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.NodesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(MockitoJUnitRunner.class)
+//@RunWith(PowerMockRunner.class)
+@PrepareForTest(MDSALUtil.class)
+public class MdSalUtilTest extends AbstractDataBrokerTest {
+ DataBroker dataBroker;
+ @Mock PacketProcessingService ppS ;
+ MDSALManager mdSalMgr = null ;
+ MockFlowForwarder flowFwder = null ;
+ MockGroupForwarder grpFwder = null ;
+ private static final String Nodeid = "openflow:1";
+
+ @Before
+ public void setUp() throws Exception {
+ dataBroker = getDataBroker() ;
+ mdSalMgr = new MDSALManager( dataBroker, ppS);
+ flowFwder = new MockFlowForwarder( dataBroker );
+ grpFwder = new MockGroupForwarder( dataBroker ) ;
+
+ PowerMockito.mockStatic(MDSALUtil.class) ;
+
+ NodeKey s1Key = new NodeKey(new NodeId("openflow:1"));
+ addFlowCapableNode(s1Key);
+ }
+
+ @Test
+ public void testInstallFlow() {
+ String dpnId = "openflow:1";
+ String tableId1 = "12";
+
+ //Install Flow 1
+ FlowEntity testFlow1 = createFlowEntity(dpnId, tableId1) ;
+ mdSalMgr.installFlow(testFlow1);
+ assertEquals(1, flowFwder.getDataChgCount());
+
+ // Install FLow 2
+ String tableId2 = "13" ;
+ FlowEntity testFlow2 = createFlowEntity(dpnId, tableId2) ;
+ mdSalMgr.installFlow(testFlow2);
+ assertEquals(2, flowFwder.getDataChgCount());
+ }
+
+ @Test
+ public void testRemoveFlow() {
+ String dpnId = "openflow:1";
+ String tableId = "13" ;
+ FlowEntity testFlow = createFlowEntity(dpnId, tableId) ;
+
+ // To test RemoveFlow add and then delete Flows
+ mdSalMgr.installFlow(testFlow) ;
+ assertEquals(1, flowFwder.getDataChgCount());
+ mdSalMgr.removeFlow(testFlow);
+ assertEquals(0, flowFwder.getDataChgCount());
+ }
+
+ @Test
+ public void testInstallGroup() {
+ // Install Group 1
+ String inport = "2" ;
+ int vlanid = 100 ;
+ GroupEntity grpEntity1 = createGroupEntity(Nodeid, inport, vlanid) ;
+
+ mdSalMgr.installGroup(grpEntity1);
+ assertEquals(1, grpFwder.getDataChgCount());
+
+ // Install Group 2
+ inport = "3" ;
+ vlanid = 100 ;
+ GroupEntity grpEntity2 = createGroupEntity(Nodeid, inport, vlanid) ;
+ mdSalMgr.installGroup(grpEntity2);
+ assertEquals(2, grpFwder.getDataChgCount());
+ }
+
+ @Test
+ public void testRemoveGroup() {
+ String inport = "2" ;
+ int vlanid = 100 ;
+ GroupEntity grpEntity = createGroupEntity(Nodeid, inport, vlanid) ;
+ // To test RemoveGroup add and then delete Group
+ mdSalMgr.installGroup(grpEntity);
+ assertEquals(1, grpFwder.getDataChgCount());
+ mdSalMgr.removeGroup(grpEntity);
+ assertEquals(0, grpFwder.getDataChgCount());
+ }
+
+ public void addFlowCapableNode(NodeKey nodeKey) throws ExecutionException, InterruptedException {
+ Nodes nodes = new NodesBuilder().setNode(Collections.<Node>emptyList()).build();
+ InstanceIdentifier<Node> flowNodeIdentifier = InstanceIdentifier.create(Nodes.class)
+ .child(Node.class, nodeKey);
+
+ FlowCapableNodeBuilder fcnBuilder = new FlowCapableNodeBuilder();
+ NodeBuilder nodeBuilder = new NodeBuilder();
+ nodeBuilder.setKey(nodeKey);
+ nodeBuilder.addAugmentation(FlowCapableNode.class, fcnBuilder.build());
+
+ WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction();
+ writeTx.put(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class), nodes);
+ writeTx.put(LogicalDatastoreType.OPERATIONAL, flowNodeIdentifier, nodeBuilder.build());
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Nodes.class), nodes);
+ writeTx.put(LogicalDatastoreType.CONFIGURATION, flowNodeIdentifier, nodeBuilder.build());
+ assertCommit(writeTx.submit());
+ }
+
+ // Methods to test the install Flow and Group
+
+ public FlowEntity createFlowEntity(String dpnId, String tableId) {
+
+ BigInteger dpId;
+ int SERVICE_ID = 0;
+ FlowEntity terminatingServiceTableFlowEntity = null;
+
+ List<ActionInfo> listActionInfo = new ArrayList<ActionInfo>();
+ listActionInfo.add(new ActionInfo(ActionType.punt_to_controller,
+ new String[] {}));
+
+ try {
+ dpId = new BigInteger(dpnId.split(":")[1]);
+
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ BigInteger COOKIE = new BigInteger("9000000", 16);
+
+ short s_tableId = Short.parseShort(tableId) ;
+
+ mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {
+ new BigInteger("0000000000000000", 16) }));
+
+ List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
+ mkInstructions.add(new InstructionInfo(InstructionType.write_actions,
+ listActionInfo));
+
+ terminatingServiceTableFlowEntity = MDSALUtil
+ .buildFlowEntity(
+ dpId,
+ s_tableId,
+ getFlowRef(s_tableId,
+ SERVICE_ID), 5, "Terminating Service Flow Entry: " + SERVICE_ID,
+ 0, 0, COOKIE
+ .add(BigInteger.valueOf(SERVICE_ID)),
+ null, null);
+ } catch (Exception e) {
+ //throw new Exception(e) ;
+ }
+
+ return terminatingServiceTableFlowEntity;
+ }
+
+ private String getFlowRef(short termSvcTable, int svcId) {
+ return new StringBuffer().append(termSvcTable).append(svcId).toString();
+ }
+
+ public GroupEntity createGroupEntity(String Nodeid, String inport, int vlanid) {
+ GroupEntity groupEntity;
+ long id = getUniqueValue(Nodeid, inport);
+ List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
+ List<ActionInfo> listActionInfo = new ArrayList<ActionInfo>();
+ if (vlanid > 0) {
+ listActionInfo.add(new ActionInfo(ActionType.push_vlan, new String[] { null }));
+ listActionInfo.add(new ActionInfo(ActionType.set_field_vlan_vid, new String[] { String.valueOf(vlanid) }));
+ }
+ listActionInfo.add(new ActionInfo(ActionType.output, new String[] { inport, "65535" }));
+ listBucketInfo.add(new BucketInfo(listActionInfo));
+
+ String groupName = "Test Group";
+ BigInteger dpnId = new BigInteger(Nodeid.split(":")[1]);
+ groupEntity = MDSALUtil.buildGroupEntity(dpnId, id, groupName, GroupTypes.GroupIndirect,
+ listBucketInfo);
+
+ return groupEntity;
+ }
+
+ private static long getUniqueValue(String nodeId, String inport) {
+
+ Long nodeIdL = Long.valueOf(nodeId.split(":")[1]);
+ Long inportL = Long.valueOf(inport);
+ long sd_set;
+ sd_set = nodeIdL * 10 + inportL;
+
+ return sd_set;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.test;
+
+import java.util.Collection;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+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;
+
+public class MockFlowForwarder extends AbstractMockForwardingRulesManager<Flow> {
+
+ private int nFlowCount = 0;
+
+ private ListenerRegistration<MockFlowForwarder> listenerRegistration;
+
+ public MockFlowForwarder( final DataBroker db) {
+ super() ;
+ registerListener(db) ;
+ }
+
+ private void registerListener(final DataBroker db) {
+ final DataTreeIdentifier<Flow> treeId = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, getWildCardPath());
+ try {
+ listenerRegistration = db.registerDataTreeChangeListener(treeId, MockFlowForwarder.this);
+ } catch (final Exception e) {
+ throw new IllegalStateException("FlowForwarder registration Listener fail! System needs restart.", e);
+ }
+ }
+
+ private InstanceIdentifier<Flow> getWildCardPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class)
+ .augmentation(FlowCapableNode.class).child(Table.class).child(Flow.class);
+ }
+
+ @Override
+ public void onDataTreeChanged(Collection<DataTreeModification<Flow>> changes) {
+ for (DataTreeModification<Flow> change : changes) {
+ final InstanceIdentifier<Flow> key = change.getRootPath().getRootIdentifier();
+ final DataObjectModification<Flow> mod = change.getRootNode();
+
+ switch (mod.getModificationType()) {
+ case DELETE:
+ nFlowCount -= 1;
+ break;
+ case SUBTREE_MODIFIED:
+ // CHECK IF RQD
+ break;
+ case WRITE:
+ if (mod.getDataBefore() == null) {
+ nFlowCount += 1;
+ } else {
+ // UPDATE COUNT UNCHANGED
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Unhandled modification type " + mod.getModificationType());
+ }
+ }
+ }
+
+ public int getDataChgCount() {
+ return nFlowCount;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.test;
+
+import java.util.Collection;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+
+public class MockGroupForwarder extends AbstractMockForwardingRulesManager<Group>{
+
+ private int nGroupCount = 0;
+ private ListenerRegistration<MockGroupForwarder> listenerRegistration ;
+
+ public MockGroupForwarder( final DataBroker db) {
+ super() ;
+ registerListener(db) ;
+ }
+
+ private void registerListener(final DataBroker db) {
+ final DataTreeIdentifier<Group> treeId = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, getWildCardPath());
+ try {
+ listenerRegistration = db.registerDataTreeChangeListener(treeId, MockGroupForwarder.this);
+ } catch (final Exception e) {
+ throw new IllegalStateException("GroupForwarder registration Listener fail! System needs restart.", e);
+ }
+ }
+
+ private InstanceIdentifier<Group> getWildCardPath() {
+ return InstanceIdentifier.create(Nodes.class).child(Node.class).
+ augmentation(FlowCapableNode.class).child(Group.class);
+ }
+
+ @Override
+ public void onDataTreeChanged(Collection<DataTreeModification<Group>> changes) {
+ for (DataTreeModification<Group> change : changes) {
+ final InstanceIdentifier<Group> key = change.getRootPath().getRootIdentifier();
+ final DataObjectModification<Group> mod = change.getRootNode();
+
+ switch (mod.getModificationType()) {
+ case DELETE:
+ nGroupCount -= 1;
+ break;
+ case SUBTREE_MODIFIED:
+ // CHECK IF RQD
+ break;
+ case WRITE:
+ if (mod.getDataBefore() == null) {
+ nGroupCount += 1;
+ } else {
+ // UPDATE COUNT UNCHANGED
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Unhandled modification type " + mod.getModificationType());
+ }
+ }
+ }
+
+ public int getDataChgCount() {
+ return nGroupCount;
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>mdsalutil-aggregator</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <name>mdsalutil</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>mdsalutil-api</module>
+ <module>mdsalutil-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>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2015 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>binding-parent</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <relativePath>../commons/binding-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>model-bgp</artifactId>
+ <version>${model.bgp.version}</version>
+ <name>${project.artifactId}</name>
+ <description>${project.artifactId}</description>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</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>
+ </dependencies>
+</project>
--- /dev/null
+module bgp {
+ namespace "urn:cisco:params:xml:ns:yang:bgp";
+ // replace with IANA namespace when assigned
+ prefix bgp;
+
+ import ietf-inet-types {
+ prefix inet;
+ revision-date "2010-09-24";
+ }
+ import ietf-yang-types {
+ prefix yang;
+ }
+
+ organization
+ "Cisco Systems
+ 170 West Tasman Drive
+ San Jose, CA 95134-1706
+ USA";
+ contact
+ "Aleksandr Zhdankin azhdanki@cisco.com
+ Keyur Patel keyupate@cisco.com
+ Alexander Clemm alex@cisco.com";
+ description
+ "This YANG module defines the generic configuration
+ data for BGP, which is common across all of the vendor
+ implementations of the protocol. It is intended that the module
+ will be extended by vendors to define vendor-specific
+ BGP configuration parameters and policies,
+ for example route maps or route policies.
+
+
+ Terms and Acronyms
+
+ BGP (bgp): Border Gateway Protocol
+
+ IP (ip): Internet Protocol
+
+ IPv4 (ipv4):Internet Protocol Version 4
+
+ IPv6 (ipv6): Internet Protocol Version 6
+
+ MED(med): Multi Exit Discriminator
+
+ IGP (igp): Interior Gateway Protocol
+
+ MTU (mtu) Maximum Transmission Unit
+ ";
+
+ revision 2013-07-15 {
+ description
+ "Initial revision.";
+ }
+
+ typedef prefix-list-ref {
+ description
+ "A reference to the prefix list which a bgp-neighbor can use.";
+ type leafref {
+ path "/prefix-lists/prefix-list/prefix-list-name";
+ }
+ }
+
+ typedef neigbour-ref {
+ description
+ "A reference to the bgp-neighbor.";
+ type leafref {
+ path "/bgp-neighbors/bgp-neighbor/as-number";
+ }
+ }
+
+ typedef bgp-peer-admin-status {
+ description
+ "Administartive status of a BGP peer.";
+ type enumeration {
+ enum "unknown";
+ enum "up";
+ enum "down";
+ }
+ }
+
+ typedef actions-enum {
+ description
+ "Permit/deny action.";
+ type enumeration {
+ enum "permit";
+ enum "deny";
+ }
+ }
+
+ grouping ACTIONS {
+ description
+ "Permit/deny action.";
+ leaf action {
+ type actions-enum;
+ mandatory true;
+ }
+ }
+
+ grouping slow-peer-config {
+ description
+ "Configure a slow-peer.";
+ container detection {
+ leaf enable {
+ type boolean;
+ default "true";
+ }
+ leaf threshold {
+ type uint16 {
+ range "120..3600";
+ }
+ }
+ }
+ leaf split-update-group {
+ type enumeration {
+ enum "dynamic";
+ enum "static";
+ }
+ }
+ }
+ grouping update-group-management {
+ description
+ "Manage peers in BGP update group.";
+ leaf split-as-override {
+ description
+ "Keeps peers with as-override in different update groups.";
+ type boolean;
+ }
+ }
+
+ grouping neighbour-base-af-config {
+ description
+ "A set of configuration parameters that is applicable to all neighbour address families.";
+ leaf active {
+ description
+ "Enable the address family for this neighbor.";
+ type boolean;
+ default "false";
+ }
+ leaf advertisement-interval {
+ description
+ "Minimum interval between sending BGP routing updates.";
+ type uint32;
+ }
+ leaf allowas-in {
+ description
+ "Accept as-path with my AS present in it.";
+ type boolean;
+ default "false";
+ }
+ leaf maximum-prefix {
+ description
+ "Maximum number of prefixes accepted from this peer.";
+ type uint32;
+ }
+ leaf next-hop-self {
+ description
+ "Enable the next hop calculation for this neighbor.";
+ type boolean;
+ default "true";
+ }
+ leaf next-hop-unchanged {
+ description
+ "Propagate next hop unchanged for iBGP paths to this neighbour.";
+ type boolean;
+ default "true";
+ }
+ container remove-private-as {
+ leaf remove-private-as-number {
+ description
+ "Remove private AS number from outbound updates.";
+ type boolean;
+ }
+ leaf replace-with-local-as {
+ description
+ "Replace private AS number with local AS.";
+ type boolean;
+ }
+ }
+ leaf route-reflector-client {
+ description
+ "Configure a neighbor as Route Reflector client.";
+ type boolean;
+ default "false";
+ }
+ leaf send-community {
+ description
+ "Send Community attribute to this neighbor.";
+ type enumeration {
+ enum "both";
+ enum "extended";
+ enum "standard";
+ }
+ default "standard";
+ }
+ uses slow-peer-config;
+ leaf soo {
+ description
+ "Site-of-Origin extended community. Format is ASN:nn or IP-address:nn";
+ type string;
+ }
+ leaf weight {
+ description
+ "Set default weight for routes from this neighbor.";
+ type uint16;
+ }
+ }
+
+ grouping neighbour-common-af-config {
+ description
+ "A set of configuration parameters that is applicable to all neighbour address families,
+ except of nsap and rtfilter.";
+ uses neighbour-base-af-config;
+ leaf prefix-list {
+ description
+ "Reference to the prefix list of this neighbour.";
+ type prefix-list-ref;
+ }
+ leaf soft-reconfiguration {
+ description
+ "Allow inbound soft reconfiguration.";
+ type boolean;
+ }
+ }
+
+ grouping neighbour-cast-af-config {
+ description
+ "A set of configuration parameters that is applicable to both unicast and multicast sub-address families.";
+ uses neighbour-common-af-config;
+ leaf propagate-dmzlink-bw {
+ description
+ "Propagate the DMZ link bandwidth.";
+ type boolean;
+ }
+ container default-originate {
+ description
+ "Originate default route to this neighbor.";
+ leaf enable {
+ type boolean;
+ default "false";
+ }
+ }
+ }
+
+ grouping neighbour-ip-multicast-af-config {
+ description
+ "A set of configuration parameters that is applicable to ip multicast.";
+ uses neighbour-cast-af-config;
+ leaf route-server-client-context {
+ description
+ "Specifies Route Server client context name.";
+ type string;
+ }
+ }
+
+ grouping neighbour-ip-unicast-af-config {
+ description
+ "A set of configuration parameters that is applicable to ip unicast.
+ This grouping is intended to be extended by vendors as necessary to describe the vendor-specific configuration parameters.";
+ uses neighbour-ip-multicast-af-config;
+ }
+
+ grouping bgp-af-config {
+ description
+ "A set of configuration parameters that is applicable to all address families of the BFP router.";
+ leaf additional-paths {
+ description
+ "Additional paths in the BGP table.";
+ type enumeration {
+ enum "all";
+ enum "best-n";
+ enum "group-best";
+ }
+ }
+ leaf advertise-best-external {
+ description
+ "Advertise best external path to internal peers.";
+ type boolean;
+ }
+ container aggregate-timer {
+ description
+ "Configure aggregation timer.";
+ leaf enable {
+ type boolean;
+ default "true";
+ }
+ leaf threshold {
+ type uint16 {
+ range "6..60";
+ }
+ }
+ }
+ container bestpath {
+ description
+ "Change the default bestpath selection.";
+ choice bestpath-selection {
+ case as-path {
+ description
+ "Configures a BGP routrer to not consider the autonomous system (AS) path during best path route selection.";
+ leaf ignore-as-path {
+ type boolean;
+ default "false";
+ }
+ }
+ case compare-routerid {
+ description
+ "Configures a BGP routrer to compare identical routes received from different external peers
+ during the best path selection process and to select the route with the lowest router ID as the best path.";
+ leaf ignore-routerid {
+ type boolean;
+ default "false";
+ }
+ }
+ case cost-community {
+ description
+ "Configures a BGP router to not evaluate the cost community attribute
+ during the best path selection process.";
+ leaf ignore-cost-community {
+ type boolean;
+ default "false";
+ }
+ }
+ case igp-metric {
+ description
+ "Configures the system to ignore the IGP metric during BGP best path selection.";
+ leaf ignore-igp-metric {
+ type boolean;
+ default "false";
+ }
+ }
+ case mad-confed {
+ description
+ "Configure a BGP routing process to compare the Multi Exit Discriminator (MED)
+ between paths learned from confederation peers.";
+ leaf enable {
+ type boolean;
+ default "false";
+ }
+ leaf missing-as-worst {
+ description
+ "Assigns a value of infinity to routes that are missing
+ the Multi Exit Discriminator (MED) attribute,
+ making the path without a MED value the least desirable path";
+ type boolean;
+ default "false";
+ }
+ }
+ }
+ }
+ leaf dampening {
+ description
+ "Enable route-flap dampening.";
+ type boolean;
+ default "false";
+ }
+ leaf propagate-dmzlink-bw {
+ description
+ "Use DMZ Link Bandwidth as weight for BGP multipaths.";
+ type boolean;
+ }
+ leaf redistribute-internal {
+ description
+ "Allow redistribution of iBGP into IGPs (dangerous)";
+ type boolean;
+ }
+ leaf scan-time {
+ description
+ "Configure background scanner interval in seconds.";
+ type uint8 {
+ range "5..60";
+ }
+ }
+ uses slow-peer-config;
+ leaf soft-reconfig-backup {
+ description
+ "Use soft-reconfiguration inbound only when route-refresh is not negotiated.";
+ type boolean;
+ }
+ }
+
+ grouping bgp-af-vpn-config {
+ description
+ "A set of configuration parameters that is applicable to vpn sub-address family on the BGP router.";
+ uses bgp-af-config;
+ uses update-group-management;
+ }
+
+ grouping bgp-af-mvpn-config {
+ description
+ "A set of configuration parameters that is applicable to mvpn sub-address family on the BGP router.";
+ leaf scan-time {
+ description
+ "Configure background scanner interval in seconds.";
+ type uint8 {
+ range "5..60";
+ }
+ }
+ uses slow-peer-config;
+ leaf soft-reconfig-backup {
+ description
+ "Use soft-reconfiguration inbound only when route-refresh is not negotiated.";
+ type boolean;
+ }
+ leaf propagate-dmzlink-bw {
+ description
+ "Use DMZ Link Bandwidth as weight for BGP multipaths.";
+ type boolean;
+ }
+ leaf rr-group {
+ description
+ "Extended community list name.";
+ type string;
+ }
+ uses update-group-management;
+ }
+
+ grouping redistribute {
+ description
+ "Redistribute information from another routing protocol.
+ This grouping is intended to be augmented by vendors to implement vendor-specific protocol redistribution configuration options.";
+ choice protocol {
+ case bgp {
+ leaf enable-bgp {
+ type boolean;
+ }
+ }
+ case ospf {
+ leaf enable-ospf {
+ type boolean;
+ }
+ }
+ case isis {
+ leaf enable-isis {
+ type boolean;
+ }
+ }
+ case connected {
+ leaf enable-connected {
+ type boolean;
+ }
+ }
+ case eigrp {
+ leaf enable-eigrp {
+ type boolean;
+ }
+ }
+ case mobile {
+ leaf enable-mobile {
+ type boolean;
+ }
+ }
+ case static {
+ leaf enable-static {
+ type boolean;
+ }
+ }
+ case rip {
+ leaf enable-rip {
+ type boolean;
+ }
+ }
+ }
+ }
+
+ grouping router-af-config {
+ description
+ "A set of configuration parameters that is applicable to all address families on the BGP router.";
+ leaf aggregate-address {
+ description
+ "Configure BGP aggregate address.";
+ type inet:ip-address;
+ }
+ leaf distance {
+ description
+ "Define an administrative distance.";
+ type uint8 {
+ range "1..255";
+ }
+ }
+ leaf network {
+ description
+ "Specify a network to announce via BGP.";
+ type inet:ip-address;
+ }
+ uses redistribute;
+ }
+
+ grouping maximum-paths {
+ description
+ "Configures packet forwarding over multiple paths.";
+ leaf number-of-path {
+ type uint8 {
+ range "1..32";
+ }
+ }
+ leaf ibgp-number-of-path {
+ type uint8 {
+ range "1..32";
+ }
+ }
+ }
+
+ container bgp-router {
+ description
+ "This is a top-level container for the BGP router.";
+ leaf local-as-number {
+ type uint32;
+ }
+ leaf local-as-identifier {
+ type inet:ip-address;
+ }
+ container rpki-config {
+ description
+ "RPKI configuration parameters.";
+ container cache-server-config {
+ description
+ "Configure the RPKI cache-server parameters in rpki-server configuration mode.";
+ choice server {
+ case ip-address {
+ leaf ip-address {
+ type inet:ip-address;
+ mandatory true;
+ }
+ }
+ case host-name {
+ leaf ip-host-address {
+ type inet:host;
+ mandatory true;
+ }
+ }
+ }
+ choice transport {
+ description
+ "Specifies a transport method for the RPKI cache.";
+ case tcp {
+ leaf tcp-port {
+ type uint32;
+ }
+ }
+ case ssh {
+ leaf ssh-port {
+ type uint32;
+ }
+ }
+ }
+ leaf user-name {
+ type string;
+ }
+ leaf password {
+ type string;
+ }
+ leaf preference-value {
+ description
+ "Specifies a preference value for the RPKI cache.
+ Setting a lower preference value is better.";
+ type uint8 {
+ range "1..10";
+ }
+ }
+ leaf purge-time {
+ description
+ "Configures the time BGP waits to keep routes from a cache after the cache session drops. Set purge time in seconds.";
+ type uint16 {
+ range "30..360";
+ }
+ }
+ choice refresh-time {
+ description
+ "Configures the time BGP waits in between sending periodic serial queries to the cache. Set refresh-time in seconds.";
+ case disable {
+ leaf refresh-time-disable {
+ type boolean;
+ }
+ }
+ case set-time {
+ leaf refresh-interval {
+ type uint16 {
+ range "15..3600";
+ }
+ }
+ }
+ }
+ choice responce-time {
+ description
+ "Configures the time BGP waits for a response after sending a serial or reset query. Set response-time in seconds.";
+ case disable {
+ leaf responce-time-disable {
+ type boolean;
+ }
+ }
+ case set-time {
+ leaf responce-interval {
+ type uint16 {
+ range "15..3600";
+ }
+ }
+ }
+ }
+ }
+ container validation-config {
+ description
+ "Controls the behavior of RPKI prefix validation processing.";
+ leaf enable {
+ description
+ "Enables RPKI origin-AS validation.";
+ type boolean;
+ default "true";
+ }
+ leaf enable-ibgp {
+ description
+ "Enables the iBGP signaling of validity state through an extended-community.";
+ type boolean;
+ }
+ choice validation-time {
+ description
+ "Sets prefix validation time (in seconds) or to set off the automatic prefix validation after an RPKI update.";
+ case validation-off {
+ leaf disable {
+ type boolean;
+ }
+ }
+ case set-time {
+ leaf prefix-validation-time {
+ description
+ "Range in seconds.";
+ type uint16 {
+ range "5..60";
+ }
+ }
+ }
+ }
+ }
+ container bestpath-computation {
+ description
+ "Configures RPKI bestpath computation options.";
+ leaf enable {
+ description
+ "Enables the validity states of BGP paths to affect the path's preference in the BGP bestpath process.";
+ type boolean;
+ }
+ leaf allow-invalid {
+ description
+ "Allows all 'invalid' paths to be considered for BGP bestpath computation.";
+ type boolean;
+ }
+ }
+ }
+ container af-configuration {
+ description
+ "Top level container for address families specific configuration of the BGP router.";
+ container ipv4 {
+ container mdt {
+ container bgp {
+ description
+ "BGP specific commands for ipv4-mdt address family/sub-addess family combination.";
+ leaf dampening {
+ description
+ "Enable route-flap dampening.";
+ type boolean;
+ default "false";
+ }
+ leaf scan-time {
+ description
+ "Configure background scanner interval in seconds.";
+ type uint8 {
+ range "5..60";
+ }
+ }
+ uses slow-peer-config;
+ leaf soft-reconfig-backup {
+ description
+ "Use soft-reconfiguration inbound only when route-refresh is not negotiated.";
+ type boolean;
+ }
+ leaf propagate-dmzlink-bw {
+ description
+ "Use DMZ Link Bandwidth as weight for BGP multipaths.";
+ type boolean;
+ }
+ }
+ }
+ container multicast {
+ container bgp {
+ description
+ "BGP specific commands for ipv4-multicast address family/sub-addess family combination.";
+ uses bgp-af-config;
+ }
+ leaf auto-summary {
+ description
+ "Enable automatic network number summarization";
+ type boolean;
+ }
+ uses router-af-config;
+ leaf default-metric {
+ description
+ "Set metric of redistributed routes.";
+ type uint32;
+ }
+ }
+ container unicast {
+ container bgp {
+ description
+ "BGP specific commands for ipv4-unicast address family/sub-addess family combination.";
+ uses bgp-af-config;
+ leaf always-compare-med {
+ description
+ "Allow comparing MED from different neighbors.";
+ type boolean;
+ default "false";
+ }
+ leaf enforce-first-as {
+ description
+ "Enforce the first AS for EBGP routes(default).";
+ type boolean;
+ default "true";
+ }
+ leaf fast-external-fallover {
+ description
+ "Immediately reset session if a link to a directly connected external peer goes down.";
+ type boolean;
+ default "true";
+ }
+ leaf suppress-inactive {
+ description
+ "Suppress routes that are not in the routing table.";
+ type boolean;
+ }
+ leaf asnotation {
+ description
+ "Sets the default asplain notation.";
+ type enumeration {
+ enum "asplain";
+ enum "dot";
+ }
+ }
+ leaf enable-client-to-client-reflection {
+ description
+ "Manages client to client route reflection.";
+ type boolean;
+ default "true";
+ }
+ leaf cluster-id {
+ description
+ "Configure Route-Reflector Cluster-id.";
+ type string;
+ }
+ container confederation {
+ description
+ "AS confederation parameters.";
+ leaf identifier {
+ description
+ "Confederation identifier.";
+ type string;
+ }
+ list peers {
+ description
+ "Confederation peers.";
+ key "as-name";
+ leaf as-name {
+ type string;
+ }
+ }
+ }
+ container consistency-checker {
+ description
+ "Consistency-checker configuration.";
+ leaf enable {
+ type boolean;
+ }
+ leaf interval {
+ description
+ "Check interval in minutes.";
+ type uint16 {
+ range "5..1440";
+ }
+ }
+ choice inconsistency-action {
+ case error-message {
+ description
+ "Specifies that when an inconsistency is found, the system will only generate a syslog message.";
+ leaf generate-error-message-only {
+ type boolean;
+ }
+ }
+ case autorepair {
+ description
+ "Specifies that when an inconsistency is found,
+ the system will generate a syslog message and take action
+ based on the type of inconsistency found.";
+ leaf perform-autorepair {
+ type boolean;
+ }
+ }
+ }
+ }
+ leaf deterministic-med {
+ description
+ "If enabled it enforce the deterministic comparison of the MED value between
+ all paths received from within the same autonomous system.";
+ type boolean;
+ }
+ container graceful-restart {
+ description
+ "Controls the BGP graceful restart capability.";
+ leaf enable {
+ type boolean;
+ }
+ leaf restart-time {
+ description
+ "Sets the maximum time period (in seconds) that the local router will wait
+ for a graceful-restart-capable neighbor to return to normal operation after a restart event occurs.";
+ type uint16 {
+ range "1..3600";
+ }
+ default "120";
+ }
+ leaf stalepath-time {
+ description
+ "Sets the maximum time period that the local router will hold stale paths for a restarting peer.";
+ type uint16 {
+ range "5..3600";
+ }
+ default "360";
+ }
+ }
+ container listener-congfig {
+ description
+ "Associates a subnet range with a BGP peer group and activate the BGP dynamic neighbors feature.";
+ leaf enable {
+ type boolean;
+ }
+ leaf limit {
+ description
+ "Sets a maximum limit number of BGP dynamic subnet range neighbors.";
+ type uint16 {
+ range "1..5000";
+ }
+ default "100";
+ }
+ leaf range {
+ description
+ "Specifies a subnet range that is to be associated with a specified peer group.";
+ type uint16 {
+ range "0..32";
+ }
+ }
+ leaf peer-group {
+ description
+ "Specifies a BGP peer group that is to be associated with the specified subnet range.";
+ type string;
+ }
+ }
+ leaf log-neighbor-changes {
+ description
+ "Log neighbor up/down and reset reason.";
+ type boolean;
+ }
+ leaf max-as-limit {
+ description
+ "Configures BGP to discard routes that have a number of autonomous system numbers in AS-path that exceed the specified value.";
+ type uint16 {
+ range "1..254";
+ }
+ }
+ container router-id {
+ description
+ "Configures a fixed router ID for the local BGP routing process.";
+ leaf enable {
+ type boolean;
+ }
+ choice config-type {
+ case static {
+ leaf ip-address {
+ type boolean;
+ }
+ }
+ case auto-config {
+ leaf enable-auto-config {
+ type boolean;
+ }
+ }
+ }
+ }
+ container transport {
+ description
+ "Manages transport session parameters.";
+ leaf enable-path-mtu-discovery {
+ description
+ "Enables transport path MTU discovery.";
+ type boolean;
+ default "true";
+ }
+ }
+ }
+ leaf auto-summary {
+ description
+ "Enable automatic network number summarization";
+ type boolean;
+ }
+ uses router-af-config;
+ uses maximum-paths;
+ leaf synchronization {
+ description
+ "Perform IGP synchronization.";
+ type boolean;
+ }
+ }
+ container mvpn {
+ container bgp {
+ description
+ "BGP specific commands for ipv4-mvpn address family/sub-addess family combination.";
+ uses bgp-af-mvpn-config;
+ }
+ leaf auto-summary {
+ description
+ "Enable automatic network number summarization.";
+ type boolean;
+ }
+ }
+ }
+ container ipv6 {
+ container multicast {
+ container bgp {
+ description
+ "BGP specific commands for ipv6-multicast address family/sub-addess family combination.";
+ uses bgp-af-config;
+ }
+ uses router-af-config;
+ }
+ container unicast {
+ container bgp {
+ description
+ "BGP specific commands for ipv6-unicast address family/sub-addess family combination.";
+ uses bgp-af-config;
+ }
+ uses router-af-config;
+ leaf default-metric {
+ description
+ "Set metric of redistributed routes.";
+ type uint32;
+ }
+ uses maximum-paths;
+ leaf synchronization {
+ description
+ "Perform IGP synchronization.";
+ type boolean;
+ }
+ }
+ container mvpn {
+ container bgp {
+ description
+ "BGP specific commands for ipv6-mvpn address family/sub-addess family combination.";
+ uses bgp-af-mvpn-config;
+ }
+ }
+ }
+ container l2vpn {
+ container vpls {
+ container bgp {
+ description
+ "BGP specific commands for l2vpn-vpls address family/sub-addess family combination.";
+ leaf scan-time {
+ description
+ "Configure background scanner interval in seconds.";
+ type uint8 {
+ range "5..60";
+ }
+ }
+ uses slow-peer-config;
+ }
+ }
+ }
+ container nsap {
+ container unicast {
+ container bgp {
+ description
+ "BGP specific commands for nsap-unicast address family/sub-addess family combination.";
+ container aggregate-timer {
+ description
+ "Configure Aggregation Timer.";
+ leaf enable {
+ type boolean;
+ default "true";
+ }
+ leaf threshold {
+ type uint16 {
+ range "6..60";
+ }
+ }
+ }
+ leaf dampening {
+ description
+ "Enable route-flap dampening.";
+ type boolean;
+ default "false";
+ }
+ leaf propagate-dmzlink-bw {
+ description
+ "Use DMZ Link Bandwidth as weight for BGP multipaths.";
+ type boolean;
+ }
+ leaf redistribute-internal {
+ description
+ "Allow redistribution of iBGP into IGPs (dangerous)";
+ type boolean;
+ }
+ leaf scan-time {
+ description
+ "Configure background scanner interval in seconds.";
+ type uint8 {
+ range "5..60";
+ }
+ }
+ uses slow-peer-config;
+ leaf soft-reconfig-backup {
+ description
+ "Use soft-reconfiguration inbound only when route-refresh is not negotiated.";
+ type boolean;
+ }
+ }
+ leaf default-metric {
+ description
+ "Set metric of redistributed routes.";
+ type uint32;
+ }
+ uses maximum-paths;
+ leaf network {
+ description
+ "Specify a network to announce via BGP.";
+ type inet:ip-address;
+ }
+ uses redistribute;
+ leaf synchronization {
+ description
+ "Perform IGP synchronization.";
+ type boolean;
+ }
+ }
+ }
+ }
+ container rtfilter {
+ container unicast {
+ container bgp {
+ description
+ "BGP specific commands for rtfilter-unicast address family/sub-addess family combination.";
+ uses slow-peer-config;
+ }
+ uses maximum-paths;
+ }
+ }
+ container vpnv4 {
+ container unicast {
+ container bgp {
+ description
+ "BGP specific commands for vpnv4-unicast address family/sub-addess family combination.";
+ uses bgp-af-vpn-config;
+ }
+ uses maximum-paths;
+ }
+ container multicast {
+ container bgp {
+ description
+ "BGP specific commands for vpnv4-multicast address family/sub-addess family combination.";
+ uses bgp-af-vpn-config;
+ }
+ uses maximum-paths;
+ }
+ }
+ container vpnv6 {
+ container unicast {
+ container bgp {
+ description
+ "BGP specific commands for vpnv6-unicast address family/sub-addess family combination.";
+ uses bgp-af-vpn-config;
+ }
+ }
+ }
+ }
+ container bgp-neighbors {
+ description
+ "The top level container for the list of neighbours of the BGP router.";
+ list bgp-neighbor {
+ key "as-number";
+ leaf as-number {
+ type uint32;
+ }
+ choice peer-address-type {
+ case ip-address {
+ leaf ip-address {
+ type inet:ip-address;
+ mandatory true;
+ }
+ }
+ case prefix {
+ leaf prefix {
+ type inet:ip-prefix;
+ mandatory true;
+ }
+ }
+ case host {
+ leaf ip-host-address {
+ type inet:host;
+ mandatory true;
+ }
+ }
+ }
+ leaf prefix-list {
+ type prefix-list-ref;
+ }
+ leaf default-action {
+ type actions-enum;
+ }
+ container af-specific-config {
+ description
+ "Address family specific configuration parameters for the neighbours.";
+ container ipv4 {
+ container mdt {
+ uses neighbour-common-af-config;
+ }
+ container unicast {
+ uses neighbour-ip-unicast-af-config;
+ }
+ container multicast {
+ uses neighbour-ip-multicast-af-config;
+ }
+ container mvpn {
+ uses neighbour-cast-af-config;
+ }
+ }
+ container ipv6 {
+ container unicast {
+ uses neighbour-ip-unicast-af-config;
+ }
+ container multicast {
+ uses neighbour-ip-multicast-af-config;
+ }
+ container mvpn {
+ uses neighbour-common-af-config;
+ }
+ }
+ container l2vpn {
+ container evpn {
+ uses neighbour-common-af-config;
+ }
+ container vpls {
+ uses neighbour-common-af-config;
+ }
+ }
+ container nsap {
+ container unicast {
+ uses neighbour-base-af-config;
+ leaf prefix-list {
+ type prefix-list-ref;
+ }
+ }
+ }
+ container rtfilter {
+ container unicast {
+ uses neighbour-base-af-config;
+ leaf soft-reconfiguration {
+ description
+ "Allow inbound soft reconfiguration.";
+ type boolean;
+ }
+ }
+ }
+ container vpnv4 {
+ container unicast {
+ uses neighbour-cast-af-config;
+ }
+ container multicast {
+ uses neighbour-cast-af-config;
+ }
+ }
+ container vpnv6 {
+ container unicast {
+ uses neighbour-cast-af-config;
+ }
+ container multicast {
+ uses neighbour-cast-af-config;
+ }
+ }
+ }
+ container bgp-neighbor-state {
+ description
+ "The operational parameters describing the neighbour state.
+ It is intended that this container may be augmented by vendors to reflect the vendor-specific operational state parameters.";
+ leaf adminStatus {
+ type bgp-peer-admin-status;
+ }
+ leaf in-lastupdatetime {
+ type yang:timestamp;
+ }
+ }
+ container bgp-neighbor-statistics {
+ description
+ "The operational parameters describing the neighbour statistics.
+ It is intended that this container may be augmented by vendors to reflect the vendor-specific staistical parameters.";
+ leaf nr-in-updates {
+ type uint32;
+ }
+ leaf nr-out-updates {
+ type uint32;
+ }
+ }
+ }
+ }
+ container prefix-lists {
+ description
+ "Contains all prefix lists defined
+ on a router.";
+ list prefix-list {
+ key "prefix-list-name";
+ description
+ "A prefix list.";
+ leaf prefix-list-name {
+ type string;
+ }
+ container prefixes {
+ list prefix {
+ key "seq-nr";
+ description
+ "A prefix is a rule with a BGP filter.
+ The left hand side of the rule is the prefix filter.
+ It specifies a set of IP addresses.
+ If a BGP announcement contains an address that matches, the
+ rule is applied. The right hand side of the rule specifies
+ the action that is to be applied.";
+ leaf seq-nr {
+ type uint16;
+ description
+ "Sequence number of the rule.
+ The sequence number is included for compatibility purposes
+ with CLI; from a machine-to-machine interface perspective,
+ it would strictly speaking not be required as list elements
+ can be arranged in a particular order.";
+ }
+ container prefix-filter {
+ choice ip-address-group {
+ case ip-address {
+ leaf ip-address {
+ type inet:ip-address;
+ mandatory true;
+ }
+ }
+ case prefix {
+ leaf prefix {
+ type inet:ip-prefix;
+ mandatory true;
+ }
+ }
+ case host {
+ leaf ip-host-address {
+ type inet:host;
+ mandatory true;
+ }
+ }
+ case ip-range {
+ leaf lower {
+ type inet:ip-address;
+ }
+ leaf upper {
+ type inet:ip-address;
+ }
+ }
+ }
+ leaf action {
+ type actions-enum;
+ mandatory true;
+ description
+ "permit/deny action";
+ }
+ container statistics {
+ leaf prefix-hit-count {
+ type uint32;
+ config false;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+module ebgp {
+
+ yang-version "1";
+
+ // namespace
+ namespace "urn:ericsson:params:xml:ns:yang:ebgp";
+
+ prefix "ericsson-bgp";
+
+ // import some basic inet types
+ import ietf-inet-types { prefix inet; revision-date "2010-09-24"; }
+
+ // meta
+ organization
+ "Ericsson Bangalore";
+
+ contact
+ "Ericsson Bangalore";
+
+ description
+ "BGP configuration model for Ericsson's implementation of
+ Opendaylight L3VPN";
+
+ revision "2015-09-01" {
+ }
+
+ container bgp {
+ config "true";
+ container config-server {
+ leaf host {
+ type inet:ipv4-address;
+ mandatory "true";
+ }
+ leaf port {
+ type uint32;
+ mandatory "true";
+ }
+ }
+
+ container as-id {
+ leaf local-as {
+ type uint32;
+ mandatory "true";
+ }
+ leaf router-id {
+ type inet:ipv4-address;
+ }
+ leaf stalepath-time {
+ type uint32;
+ default 360;
+ }
+ leaf announce-fbit {
+ type boolean;
+ }
+ }
+
+ container graceful-restart {
+ leaf stalepath-time {
+ type uint32;
+ mandatory "true";
+ }
+ }
+
+ container logging {
+ leaf file {
+ type string;
+ }
+ leaf level {
+ type string;
+ }
+ }
+
+ list neighbors {
+ key "address";
+ leaf address {
+ type inet:ipv4-address;
+ mandatory "true";
+ }
+ leaf remote-as {
+ type uint32;
+ mandatory "true";
+ }
+ container ebgp-multihop {
+ leaf nhops {
+ type uint32;
+ }
+ leaf peer-ip {
+ type leafref {
+ path "/ericsson-bgp:bgp/neighbors/address";
+ }
+ }
+ }
+ container update-source {
+ leaf source-ip {
+ type inet:ipv4-address;
+ }
+ leaf peer-ip {
+ type leafref {
+ path "/ericsson-bgp:bgp/neighbors/address";
+ }
+ }
+ }
+ list address-families {
+ key "afi safi";
+ leaf afi {
+ type uint32;
+ mandatory "true";
+ }
+ leaf safi {
+ type uint32;
+ mandatory "true";
+ }
+ leaf peer-ip {
+ type leafref {
+ path "/ericsson-bgp:bgp/neighbors/address";
+ }
+ }
+ } //addr-families
+ } // neighbhors
+
+ list networks {
+ key "rd prefix-len";
+ leaf rd {
+ type string;
+ }
+ leaf prefix-len {
+ type string;
+ }
+ leaf nexthop {
+ type inet:ipv4-address;
+ mandatory "false";
+ }
+ leaf label {
+ type uint32;
+ mandatory "false";
+ }
+ } // networks
+
+ list vrfs {
+ key "rd";
+ leaf rd {
+ type string;
+ }
+ leaf-list import-rts {
+ type string;
+ }
+ leaf-list export-rts {
+ type string;
+ }
+ }
+ } // bgp
+}
--- /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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>natservice-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.yangtools</groupId>
+ <artifactId>yang-common</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-20130715</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+module odl-nat {
+ namespace "urn:opendaylight:vpnservice:natservice";
+ prefix odl-nat;
+
+ import ietf-yang-types { prefix "yang"; /*revision-date 2013-07-15; */}
+ import ietf-inet-types { prefix "inet"; }
+
+ revision "2016-01-11" {
+ description "NAT Manager module";
+ }
+
+ container external-networks {
+ list networks {
+ key id;
+ leaf id {
+ type yang:uuid;
+ }
+ leaf vpnid { type yang:uuid; }
+ leaf-list router-ids { type yang:uuid; }
+ }
+ }
+
+ container ext-routers {
+ list routers {
+ key router-name;
+ leaf router-name { type string; }
+ leaf network-id { type yang:uuid; }
+ leaf enable-snat { type boolean; }
+ leaf-list external-ips {
+ type string; //format - ipaddress\prefixlength
+ }
+ leaf-list subnet-ids { type yang:uuid; }
+ leaf ext_gw_mac_address { type string; }
+ }
+ }
+
+
+ grouping external-interface-info {
+ leaf internal-ip { type string; }
+ leaf external-ip { type string; }
+ leaf label { type uint16; config false; }
+ }
+
+ container floating-ip-info {
+ config true;
+ list router-ports {
+ key router-id;
+ leaf router-id { type string; }
+ leaf external-network-id { type yang:uuid; }
+ list ports {
+ key port-name;
+ leaf port-name { type string; }
+ list ip-mapping {
+ key "internal-ip";
+ uses external-interface-info;
+ }
+ }
+ }
+ }
+
+ container napt-switches {
+ list router-to-napt-switch {
+ key router-name;
+ leaf router-name { type string; }
+ leaf primary-switch-id { type uint64; }
+ }
+ }
+
+ grouping ip-port-entity {
+ leaf ip-address { type string; }
+ leaf port-num { type uint16; }
+ }
+
+ typedef protocol-types {
+ type enumeration {
+ enum TCP;
+ enum UDP;
+ }
+ }
+
+ container intext-ip-port-map {
+ config true;
+ list ip-port-mapping {
+ key router-id;
+ leaf router-id { type uint32; }
+ list intext-ip-protocol-type {
+ key protocol;
+ leaf protocol { type protocol-types; }
+ list ip-port-map {
+ key ip-port-internal;
+ description "internal to external ip-port mapping";
+ leaf ip-port-internal { type string; }
+ container ip-port-external {
+ uses ip-port-entity;
+ }
+ }
+ }
+ }
+ }
+
+ container snatint-ip-port-map {
+ list intip-port-map {
+ key router-id;
+ leaf router-id { type uint32; }
+ list ip-port {
+ key internal-ip;
+ leaf internal-ip { type string; }
+ list int-ip-proto-type {
+ key protocol;
+ leaf protocol { type protocol-types; }
+ leaf-list ports { type uint16; }
+ }
+ }
+ }
+ }
+
+ container intext-ip-map {
+ config false;
+ list ip-mapping {
+ key segment-id;
+ leaf segment-id { type uint32; }
+ list ip-map {
+ key internal-ip;
+ leaf internal-ip { type string; }
+ leaf external-ip { type string; }
+ leaf label {type uint32;}
+ }
+ }
+ }
+
+ container router-to-vpn-mapping {
+ list routermapping {
+ key router-name;
+ leaf router-name { type string; }
+ leaf vpn-id { type uint32; }
+ leaf vpn-name { type string; }
+ }
+ }
+
+ container router-id-name {
+ list routerIds {
+ key router-id;
+ leaf router-id {type uint32;}
+ leaf router-name { type string; }
+ }
+ }
+
+ container external-ips-counter {
+ config false;
+ list external-counters{
+ key segment-id;
+ leaf segment-id { type uint32; }
+ list external-ip-counter {
+ key external-ip;
+ leaf external-ip { type string; }
+ leaf counter { type uint8; }
+ }
+ }
+ }
+}
--- /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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>natservice-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+ <properties>
+ <powermock.version>1.6.4</powermock.version>
+ <mockitoall.version>1.10.19</mockitoall.version>
+</properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>natservice-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mdsalutil-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>itm-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgpmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>vpnmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>fibmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>idmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>interfacemgr-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>neutronvpn-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin.model</groupId>
+ <artifactId>model-flow-service</artifactId>
+ <version>${openflowplugin.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-net</groupId>
+ <artifactId>commons-net</artifactId>
+ </dependency>
+ <!-- Only for unit-test -->
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <version>${mockitoall.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>${powermock.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${powermock.version}</version>
+ <scope>test</scope>
+ </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:natservice:impl?module=natservice-impl&revision=2016-01-11</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:mdsalutil:api?module=odl-mdsalutil&revision=2015-04-10</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:bgpmanager:api?module=bgpmanager-api&revision=2015-04-20</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:mdsalutil:api?module=odl-mdsalutil&revision=2015-04-10</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:natservice:impl">prefix:natservice-impl</type>
+ <name>natservice-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>
+ <rpc-registry>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+ <name>binding-rpc-broker</name>
+ </rpc-registry>
+ <bgpmanager>
+ <type xmlns:bgpmanager="urn:opendaylight:params:xml:ns:yang:bgpmanager:api">bgpmanager:bgpmanager-api</type>
+ <name>bgpmanager</name>
+ </bgpmanager>
+ <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>
+ <mdsalutil>
+ <type xmlns:mdsalutil="urn:opendaylight:params:xml:ns:yang:mdsalutil:api">mdsalutil:odl-mdsalutil</type>
+ <name>mdsalutil-service</name>
+ </mdsalutil>
+ </module>
+ </modules>
+ </data>
+ </configuration>
+</snapshot>
--- /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.natservice.internal;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+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.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AddDpnEvent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.add.dpn.event.AddEventData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.RemoveDpnEvent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.OdlL3vpnListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ext.routers.Routers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class DpnInVpnListener implements OdlL3vpnListener {
+ private static final Logger LOG = LoggerFactory.getLogger(DpnInVpnListener.class);
+ private DataBroker dataBroker;
+ private SNATDefaultRouteProgrammer defaultRouteProgrammer;
+ private NaptSwitchHA naptSwitchHA;
+ private IMdsalApiManager mdsalManager;
+ private IdManagerService idManager;
+
+ public DpnInVpnListener(DataBroker dataBroker) {
+ this.dataBroker = dataBroker;
+ }
+
+ void setDefaultProgrammer(SNATDefaultRouteProgrammer defaultRouteProgrammer) {
+ this.defaultRouteProgrammer = defaultRouteProgrammer;
+ }
+
+ void setNaptSwitchHA(NaptSwitchHA switchHA) {
+ naptSwitchHA = switchHA;
+ }
+
+ void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ public void setIdManager(IdManagerService idManager) {
+ this.idManager = idManager;
+ }
+
+ public void onAddDpnEvent(AddDpnEvent notification) {
+/*
+ AddEventData eventData = notification.getAddEventData();
+ BigInteger dpnId = eventData.getDpnId();
+ String vpnName = eventData.getVpnName();
+ LOG.info("Received add dpn {} in vpn {} event", dpnId, vpnName);
+ String routerId = NatUtil.getRouterIdfromVpnId(dataBroker, vpnName);
+ if (routerId != null) {
+ //check router is associated to external network
+ InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerId);
+ Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+ if (routerData.isPresent()) {
+ Uuid networkId = routerData.get().getNetworkId();
+ if(networkId != null) {
+ LOG.debug("Router {} is associated with ext nw {}", routerId, networkId);
+ long vpnId = NatUtil.readVpnId(dataBroker, vpnName);
+ if(vpnId != NatConstants.INVALID_ID) {
+ //Install default entry in FIB to SNAT table
+ LOG.debug("Installing default route in FIB on dpn {} for vpn {} ...", dpnId, vpnName);
+ defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId);
+ } else {
+ LOG.debug("Add DPN Event: Could not read vpnId for vpnName {}", vpnName);
+ }
+ if (routerData.get().isEnableSnat()) {
+ LOG.info("SNAT enabled for router {}", routerId);
+ handleSNATForDPN(dpnId, routerId);
+ } else {
+ LOG.info("SNAT is not enabled for router {} to handle addDPN event {}", routerId, dpnId);
+ }
+ }
+ }
+ }
+*/
+ }
+
+ void handleSNATForDPN(BigInteger dpnId, String routerName) {
+ //Check if primary and secondary switch are selected, If not select the role
+ //Install select group to NAPT switch
+ //Install default miss entry to NAPT switch
+/*
+ BigInteger naptSwitch;
+ try {
+ Long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ if (routerId == NatConstants.INVALID_ID) {
+ LOG.error("Invalid routerId returned for routerName {}",routerName);
+ return;
+ }
+ BigInteger naptId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
+ if (naptId == null || naptId.equals(BigInteger.ZERO)) {
+ LOG.debug("No Naptswitch is selected for router {}", routerName);
+
+ naptSwitch = dpnId;
+ boolean naptstatus = naptSwitchHA.updateNaptSwitch(routerName, naptSwitch);
+ if(!naptstatus) {
+ LOG.error("Failed to update newNaptSwitch {} for routername {}",naptSwitch,routerName);
+ return;
+ }
+ LOG.debug("Switch {} is elected as NaptSwitch for router {}",dpnId,routerName);
+
+ //installing group
+ List<BucketInfo> bucketInfo = naptSwitchHA.handleGroupInPrimarySwitch();
+ naptSwitchHA.installSnatGroupEntry(naptSwitch,bucketInfo,routerName);
+
+ naptSwitchHA.installSnatFlows(routerName,routerId,naptSwitch);
+
+ } else {
+ LOG.debug("Napt switch with Id {} is already elected for router {}",naptId, routerName);
+ naptSwitch = naptId;
+
+ //installing group
+ List<BucketInfo> bucketInfo = naptSwitchHA.handleGroupInNeighborSwitches(dpnId, routerName, naptSwitch);
+ if (bucketInfo == null) {
+ LOG.debug("Failed to populate bucketInfo for dpnId {} routername {} naptSwitch {}",dpnId,routerName,
+ naptSwitch);
+ return;
+ }
+ naptSwitchHA.installSnatGroupEntry(dpnId, bucketInfo, routerName);
+ }
+ // Install miss entry (table 26) pointing to group
+ long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
+ FlowEntity flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId,NatConstants.ADD_FLOW);
+ if (flowEntity == null) {
+ LOG.debug("Failed to populate flowentity for router {} with dpnId {} groupId {}",routerName,dpnId,groupId);
+ return;
+ }
+ LOG.debug("Successfully installed flow for dpnId {} router {} group {}",dpnId,routerName,groupId);
+ mdsalManager.installFlow(flowEntity);
+ } catch (Exception ex) {
+ LOG.error("Exception in handleSNATForDPN method : {}",ex);
+ }
+*/
+ }
+
+ public void onRemoveDpnEvent(RemoveDpnEvent notification) {
+/*
+ RemoveEventData eventData = notification.getRemoveEventData();
+ BigInteger dpnId = eventData.getDpnId();
+ String vpnName = eventData.getVpnName();
+ LOG.info("Received remove dpn {} in vpn {} event", dpnId, vpnName);
+ String routerId = NatUtil.getRouterIdfromVpnId(dataBroker, vpnName);
+ if (routerId != null) {
+ //check router is associated to external network
+ InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerId);
+ Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+ if (routerData.isPresent()) {
+ Uuid networkId = routerData.get().getNetworkId();
+ if(networkId != null) {
+ LOG.debug("Router {} is associated with ext nw {}", routerId, networkId);
+ long vpnId = NatUtil.readVpnId(dataBroker, vpnName);
+ if(vpnId != NatConstants.INVALID_ID) {
+ //Remove default entry in FIB
+ LOG.debug("Removing default route in FIB on dpn {} for vpn {} ...", dpnId, vpnName);
+ defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId);
+ } else {
+ LOG.debug("Remove DPN Event: Could not read vpnId for vpnName {}", vpnName);
+ }
+ if (routerData.get().isEnableSnat()) {
+ LOG.info("SNAT enabled for router {}", routerId);
+ removeSNATFromDPN(dpnId,routerId);
+ } else {
+ LOG.info("SNAT is not enabled for router {} to handle removeDPN event {}", routerId, dpnId);
+ }
+ }
+ }
+ }
+*/
+ }
+
+ /*void removeSNATFromDPN(BigInteger dpnId, String routerName) {
+ //irrespective of naptswitch or non-naptswitch, SNAT default miss entry need to be removed
+ //remove miss entry to NAPT switch
+ //if naptswitch elect new switch and install Snat flows and remove those flows in oldnaptswitch
+
+ Long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ if (routerId == NatConstants.INVALID_ID) {
+ LOG.error("Invalid routerId returned for routerName {}",routerName);
+ return;
+ }
+ BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
+ if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
+ LOG.debug("No naptSwitch is selected for router {}", routerName);
+ return;
+ }
+ try {
+ boolean naptStatus = naptSwitchHA.isNaptSwitchDown(routerName,dpnId,naptSwitch);
+ if (!naptStatus) {
+ LOG.debug("NaptSwitchDown: Switch with DpnId {} is not naptSwitch for router {}",
+ dpnId, routerName);
+ } else {
+ naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName,naptSwitch);
+ }
+ } catch (Exception ex) {
+ LOG.debug("Exception while handling naptSwitch down for router {} : {}",routerName,ex);
+ }
+
+ long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
+ FlowEntity flowEntity = null;
+ try {
+ flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId, NatConstants.DEL_FLOW);
+ if (flowEntity == null) {
+ LOG.debug("Failed to populate flowentity for router {} with dpnId {} groupIs {}",routerName,dpnId,groupId);
+ return;
+ }
+ LOG.debug("NAT Service : Removing default SNAT miss entry flow entity {}",flowEntity);
+ mdsalManager.removeFlow(flowEntity);
+
+ } catch (Exception ex) {
+ LOG.debug("NAT Service : Failed to remove default SNAT miss entry flow entity {} : {}",flowEntity,ex);
+ return;
+ }
+ LOG.debug("NAT Service : Removed default SNAT miss entry flow for dpnID {} with routername {}", dpnId, routerName);
+
+ //remove group
+ GroupEntity groupEntity = null;
+ try {
+ groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
+ GroupTypes.GroupAll, null);
+ LOG.info("NAT Service : Removing NAPT GroupEntity:{}", groupEntity);
+ mdsalManager.removeGroup(groupEntity);
+ } catch (Exception ex) {
+ LOG.debug("NAT Service : Failed to remove group entity {} : {}",groupEntity,ex);
+ return;
+ }
+ LOG.debug("NAT Service : Removed default SNAT miss entry flow for dpnID {} with routerName {}", dpnId, routerName);
+ }*/
+}
\ 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.natservice.internal;
+
+import java.util.concurrent.BlockingQueue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EventDispatcher implements Runnable {
+ private BlockingQueue<NAPTEntryEvent> eventQueue;
+ private NaptEventHandler naptEventHandler;
+ private static final Logger LOG = LoggerFactory.getLogger(NaptManager.class);
+
+ EventDispatcher(BlockingQueue<NAPTEntryEvent> eventQueue, NaptEventHandler naptEventHandler){
+ this.eventQueue = eventQueue;
+ this.naptEventHandler = naptEventHandler;
+ }
+
+ public void addNaptEvent(NAPTEntryEvent naptEntryEvent){
+ this.eventQueue.add(naptEntryEvent);
+ }
+
+ public void run(){
+ while(true) {
+ try {
+ NAPTEntryEvent event = eventQueue.take();
+ naptEventHandler.handleEvent(event);
+ } catch (InterruptedException e) {
+ LOG.error("EventDispatcher : Error in handling the event queue : ", e.getMessage());
+ e.printStackTrace();
+ }
+ }
+ }
+}
--- /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.natservice.internal;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ExternalNetworks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.networks.Networks;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+
+import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.ActionType;
+import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
+import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
+import org.opendaylight.vpnservice.mdsalutil.InstructionType;
+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.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+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.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import com.google.common.base.Optional;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.ArrayList;
+
+
+public class ExternalNetworkListener extends org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener<Networks> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(ExternalNetworkListener.class);
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private IMdsalApiManager mdsalManager;
+
+ public ExternalNetworkListener (final DataBroker db) {
+ super(Networks.class);
+ broker = db;
+ //registerListener(db);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("ExternalNetwork Listener Closed");
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ getWildCardPath(), ExternalNetworkListener.this, AsyncDataBroker.DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("External Network DataChange listener registration fail!", e);
+ throw new IllegalStateException("External Network registration Listener failed.", e);
+ }
+ }
+
+ private InstanceIdentifier<Networks> getWildCardPath() {
+ return InstanceIdentifier.create(ExternalNetworks.class).child(Networks.class);
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ @Override
+ protected void add(final InstanceIdentifier<Networks> identifier,
+ final Networks nw) {
+ LOG.trace("External Network add mapping method - key: " + identifier + ", value=" + nw );
+ processExternalNwAdd(identifier, nw);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Networks> identifier, Networks nw) {
+ LOG.trace("External Network remove mapping method - key: " + identifier + ", value=" + nw );
+ processExternalNwDel(identifier, nw);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Networks> identifier, Networks original, Networks update) {
+ LOG.trace("External Network update mapping method - key: " + identifier + ", original=" + original + ", update=" + update );
+ //check if a new router has been added or an already existing router has been deleted from the external nw to router association
+ List<Uuid> oldRtrs = original.getRouterIds();
+ List<Uuid> newRtrs = update.getRouterIds();
+ if (oldRtrs != newRtrs) {
+ //handle both addition and removal of routers
+ for (Uuid rtr : newRtrs) {
+ if (oldRtrs.contains(rtr)) {
+ oldRtrs.remove(rtr);
+ } else {
+ // new router case
+ //Routers added need to have the corresponding default Fib entry added to the switches in the router
+ String routerId = rtr.getValue();
+ addOrDelDefFibRouteToSNAT(routerId, true);
+
+ }
+ }
+
+ //Routers removed need to have the corresponding default Fib entry removed from the switches in the router
+ for (Uuid rtr : oldRtrs) {
+ String routerId = rtr.getValue();
+ addOrDelDefFibRouteToSNAT(routerId, false);
+ }
+ }
+ }
+
+ private void processExternalNwAdd(final InstanceIdentifier<Networks> identifier,
+ final Networks network) {
+ LOG.trace("Add event - key: {}, value: {}", identifier, network);
+ List<Uuid> routerList = network.getRouterIds();
+
+ if(routerList == null) {
+ LOG.debug("No routers associated with external network {}", identifier);
+ return;
+ }
+
+ for(Uuid router: routerList) {
+ String routerId = router.getValue();
+ addOrDelDefFibRouteToSNAT(routerId, true);
+ }
+ }
+
+ private void processExternalNwDel(final InstanceIdentifier<Networks> identifier,
+ final Networks network) {
+ LOG.trace("Add event - key: {}, value: {}", identifier, network);
+ List<Uuid> routerList = network.getRouterIds();
+
+ for(Uuid router: routerList) {
+ String routerId = router.getValue();
+ addOrDelDefFibRouteToSNAT(routerId, false);
+ }
+ }
+
+ private void addOrDelDefFibRouteToSNAT(String routerId, boolean create) {
+ //Router ID is used as the internal VPN's name, hence the vrf-id in VpnInstance Op DataStore
+ InstanceIdentifier<VpnInstanceOpDataEntry> id = NatUtil.getVpnInstanceOpDataIdentifier(routerId);
+ Optional<VpnInstanceOpDataEntry> vpnInstOp = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ if (vpnInstOp.isPresent()) {
+ List<VpnToDpnList> dpnListInVpn = vpnInstOp.get().getVpnToDpnList();
+ for (VpnToDpnList dpn : dpnListInVpn) {
+ BigInteger dpnId = dpn.getDpnId();
+ long vpnId = NatUtil.readVpnId(broker, vpnInstOp.get().getVrfId());
+ if (create == true) {
+ installDefNATRouteInDPN(dpnId, vpnId);
+ } else {
+ removeDefNATRouteInDPN(dpnId, vpnId);
+ }
+ }
+ }
+ }
+
+ private FlowEntity buildDefNATFlowEntity(BigInteger dpId, long vpnId) {
+
+ InetAddress defaultIP = null;
+
+ try {
+ defaultIP = InetAddress.getByName("0.0.0.0");
+
+ } catch (UnknownHostException e) {
+ LOG.error("UnknowHostException in buildDefNATFlowEntity. Failed to build FIB Table Flow for Default Route to NAT table ");
+ return null;
+ }
+
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+
+ //add match for default route "0.0.0.0/0"
+ //matches.add(new MatchInfo(MatchFieldType.ipv4_src, new long[] {
+ // NatUtil.getIpAddress(defaultIP.getAddress()), 0 }));
+
+ //add match for vrfid
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
+
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.PSNAT_TABLE }));
+
+ String flowRef = NatUtil.getFlowRef(dpId, NatConstants.L3_FIB_TABLE, defaultIP);
+
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.L3_FIB_TABLE, flowRef,
+ NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_DNAT_TABLE, matches, instructions);
+
+ return flowEntity;
+
+
+ }
+
+ private void installDefNATRouteInDPN(BigInteger dpnId, long vpnId) {
+ FlowEntity flowEntity = buildDefNATFlowEntity(dpnId, vpnId);
+ if(flowEntity == null) {
+ LOG.error("Flow entity received is NULL. Cannot proceed with installation of Default NAT flow");
+ return;
+ }
+ mdsalManager.installFlow(flowEntity);
+ }
+
+ private void removeDefNATRouteInDPN(BigInteger dpnId, long vpnId) {
+ FlowEntity flowEntity = buildDefNATFlowEntity(dpnId, vpnId);
+ if(flowEntity == null) {
+ LOG.error("Flow entity received is NULL. Cannot proceed with installation of Default NAT flow");
+ return;
+ }
+ mdsalManager.removeFlow(flowEntity);
+ }
+
+
+}
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.vpnservice.natservice.internal;\r
+\r
+import com.google.common.base.Optional;\r
+\r
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;\r
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
+import org.opendaylight.vpnservice.datastoreutils.AsyncDataTreeChangeListenerBase;\r
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;\r
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceInput;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceInputBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceOutput;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ExternalNetworks;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.IntextIpMap;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.RouterPorts;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.Ports;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.ports.IpMapping;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMappingKey;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.NaptSwitches;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.networks.Networks;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitch;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;\r
+import org.opendaylight.yangtools.concepts.ListenerRegistration;\r
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;\r
+import org.opendaylight.yangtools.yang.common.RpcResult;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+import java.math.BigInteger;\r
+import java.util.List;\r
+import java.util.concurrent.ExecutionException;\r
+import java.util.concurrent.Future;\r
+\r
+import org.opendaylight.bgpmanager.api.IBgpManager;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.FibRpcService;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.VpnRpcService;\r
+\r
+/**\r
+ * Created by ESUMAMS on 1/21/2016.\r
+ */\r
+public class ExternalNetworksChangeListener extends AsyncDataTreeChangeListenerBase<Networks, ExternalNetworksChangeListener>\r
+{\r
+ private static final Logger LOG = LoggerFactory.getLogger( ExternalNetworksChangeListener.class);\r
+\r
+ private ListenerRegistration<DataChangeListener> listenerRegistration;\r
+ private final DataBroker dataBroker;\r
+ private IMdsalApiManager mdsalManager;\r
+ //private VpnFloatingIpHandler vpnFloatingIpHandler;\r
+ private FloatingIPListener floatingIpListener;\r
+ private ExternalRoutersListener externalRouterListener;\r
+ private OdlInterfaceRpcService interfaceManager;\r
+ private NaptManager naptManager;\r
+\r
+ private IBgpManager bgpManager;\r
+ private VpnRpcService vpnService;\r
+ private FibRpcService fibService;\r
+\r
+\r
+ private ExternalRoutersListener externalRoutersListener;\r
+\r
+ void setMdsalManager(IMdsalApiManager mdsalManager) {\r
+ this.mdsalManager = mdsalManager;\r
+ }\r
+\r
+ void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {\r
+ this.interfaceManager = interfaceManager;\r
+ }\r
+\r
+ void setFloatingIpListener(FloatingIPListener floatingIpListener) {\r
+ this.floatingIpListener = floatingIpListener;\r
+ }\r
+\r
+ void setExternalRoutersListener(ExternalRoutersListener externalRoutersListener) {\r
+ this.externalRouterListener = externalRoutersListener;\r
+ }\r
+\r
+ public void setBgpManager(IBgpManager bgpManager) {\r
+ this.bgpManager = bgpManager;\r
+ }\r
+\r
+ public void setNaptManager(NaptManager naptManager) {\r
+ this.naptManager = naptManager;\r
+ }\r
+\r
+ public void setVpnService(VpnRpcService vpnService) {\r
+ this.vpnService = vpnService;\r
+ }\r
+\r
+ public void setFibService(FibRpcService fibService) {\r
+ this.fibService = fibService;\r
+ }\r
+\r
+ public void setListenerRegistration(ListenerRegistration<DataChangeListener> listenerRegistration) {\r
+ this.listenerRegistration = listenerRegistration;\r
+ }\r
+\r
+ public ExternalNetworksChangeListener(final DataBroker dataBroker ) {\r
+ super( Networks.class, ExternalNetworksChangeListener.class );\r
+ this.dataBroker = dataBroker;\r
+ }\r
+\r
+\r
+ protected InstanceIdentifier<Networks> getWildCardPath() {\r
+ return InstanceIdentifier.create(ExternalNetworks.class).child(Networks.class);\r
+ }\r
+\r
+\r
+ @Override\r
+ protected void add(InstanceIdentifier<Networks> identifier, Networks networks) {\r
+\r
+ }\r
+\r
+ @Override\r
+ protected ExternalNetworksChangeListener getDataTreeChangeListener() {\r
+ return ExternalNetworksChangeListener.this;\r
+ }\r
+\r
+ @Override\r
+ protected void remove(InstanceIdentifier<Networks> identifier, Networks networks) {\r
+ if( identifier == null || networks == null || networks.getRouterIds().isEmpty() ) {\r
+ LOG.info( "ExternalNetworksChangeListener:remove:: returning without processing since networks/identifier is null" );\r
+ return;\r
+ }\r
+\r
+ for( Uuid routerId: networks.getRouterIds() ) {\r
+ String routerName = routerId.toString();\r
+\r
+ InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitchInstanceIdentifier =\r
+ getRouterToNaptSwitchInstanceIdentifier( routerName);\r
+\r
+ MDSALUtil.syncDelete( dataBroker, LogicalDatastoreType.OPERATIONAL, routerToNaptSwitchInstanceIdentifier );\r
+\r
+ LOG.debug( "ExternalNetworksChangeListener:delete:: successful deletion of data in napt-switches container" );\r
+ }\r
+ }\r
+\r
+ private static InstanceIdentifier<RouterToNaptSwitch> getRouterToNaptSwitchInstanceIdentifier( String routerName ) {\r
+\r
+ return InstanceIdentifier.builder( NaptSwitches.class )\r
+ .child( RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();\r
+\r
+ }\r
+\r
+ public void close() throws Exception {\r
+ if (listenerRegistration != null) {\r
+ try {\r
+ listenerRegistration.close();\r
+ }\r
+ catch (final Exception e) {\r
+ LOG.error("Error when cleaning up ExternalNetworksChangeListener.", e);\r
+ }\r
+\r
+ listenerRegistration = null;\r
+ }\r
+ LOG.debug("ExternalNetworksChangeListener Closed");\r
+ }\r
+\r
+\r
+ @Override\r
+ protected void update(InstanceIdentifier<Networks> identifier, Networks original, Networks update) {\r
+ //Check for VPN disassociation\r
+ Uuid originalVpn = original.getVpnid();\r
+ Uuid updatedVpn = update.getVpnid();\r
+ if(originalVpn == null && updatedVpn != null) {\r
+ //external network is dis-associated from L3VPN instance\r
+ associateExternalNetworkWithVPN(update);\r
+ } else if(originalVpn != null && updatedVpn == null) {\r
+ //external network is associated with vpn\r
+ disassociateExternalNetworkFromVPN(update, originalVpn.getValue());\r
+ //Remove the SNAT entries\r
+ removeSnatEntries(original, original.getId());\r
+ }\r
+ }\r
+\r
+ private void removeSnatEntries(Networks original, Uuid networkUuid) {\r
+ List<Uuid> routerUuids = original.getRouterIds();\r
+ for (Uuid routerUuid : routerUuids) {\r
+ Long routerId = NatUtil.getVpnId(dataBroker, routerUuid.getValue());\r
+ if (routerId == NatConstants.INVALID_ID) {\r
+ LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerUuid.getValue());\r
+ return;\r
+ }\r
+ List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,routerId);\r
+ externalRouterListener.handleDisableSnatInternetVpn(routerUuid.getValue(), networkUuid, externalIps, false, original.getVpnid().getValue());\r
+ }\r
+ }\r
+\r
+ private void associateExternalNetworkWithVPN(Networks network) {\r
+ List<Uuid> routerIds = network.getRouterIds();\r
+ for(Uuid routerId : routerIds) {\r
+ //long router = NatUtil.getVpnId(dataBroker, routerId.getValue());\r
+\r
+ InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerId.getValue());\r
+ Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);\r
+ if(!optRouterPorts.isPresent()) {\r
+ LOG.debug("Could not read Router Ports data object with id: {} to handle associate ext nw {}", routerId, network.getId());\r
+ continue;\r
+ }\r
+ RouterPorts routerPorts = optRouterPorts.get();\r
+ List<Ports> interfaces = routerPorts.getPorts();\r
+ for(Ports port : interfaces) {\r
+ String portName = port.getPortName();\r
+ BigInteger dpnId = getDpnForInterface(interfaceManager, portName);\r
+ if(dpnId.equals(BigInteger.ZERO)) {\r
+ LOG.debug("DPN not found for {}, skip handling of ext nw {} association", portName, network.getId());\r
+ continue;\r
+ }\r
+ List<IpMapping> ipMapping = port.getIpMapping();\r
+ for(IpMapping ipMap : ipMapping) {\r
+ String externalIp = ipMap.getExternalIp();\r
+ //remove all VPN related entries\r
+ floatingIpListener.createNATFlowEntries(dpnId, portName, routerId.getValue(), network.getId(), ipMap.getInternalIp(), externalIp);\r
+ }\r
+ }\r
+ }\r
+\r
+ // SNAT\r
+ for(Uuid routerId : routerIds) {\r
+ LOG.debug("NAT Service : associateExternalNetworkWithVPN() for routerId {}", routerId);\r
+ Uuid networkId = network.getId();\r
+ if(networkId == null) {\r
+ LOG.error("NAT Service : networkId is null for the router ID {}", routerId);\r
+ return;\r
+ }\r
+ final String vpnName = network.getVpnid().getValue();\r
+ if(vpnName == null) {\r
+ LOG.error("NAT Service : No VPN associated with ext nw {} for router {}", networkId, routerId);\r
+ return;\r
+ }\r
+\r
+ BigInteger dpnId = new BigInteger("0");\r
+ InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch = NatUtil.buildNaptSwitchRouterIdentifier(routerId.getValue());\r
+ Optional<RouterToNaptSwitch> rtrToNapt = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, routerToNaptSwitch );\r
+ if(rtrToNapt.isPresent()) {\r
+ dpnId = rtrToNapt.get().getPrimarySwitchId();\r
+ }\r
+ LOG.debug("NAT Service : got primarySwitch as dpnId{} ", dpnId);\r
+\r
+ Long routerIdentifier = NatUtil.getVpnId(dataBroker, routerId.getValue());\r
+ InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping> idBuilder =\r
+ InstanceIdentifier.builder(IntextIpMap.class).child(org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMappingKey(routerIdentifier));\r
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping> id = idBuilder.build();\r
+ Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping> ipMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);\r
+ if (ipMapping.isPresent()) {\r
+ List<IpMap> ipMaps = ipMapping.get().getIpMap();\r
+ for (IpMap ipMap : ipMaps) {\r
+ String externalIp = ipMap.getExternalIp();\r
+ LOG.debug("NAT Service : got externalIp as {}", externalIp);\r
+ LOG.debug("NAT Service : About to call advToBgpAndInstallFibAndTsFlows for dpnId {}, vpnName {} and externalIp {}", dpnId, vpnName, externalIp);\r
+ externalRouterListener.advToBgpAndInstallFibAndTsFlows(dpnId, NatConstants.INBOUND_NAPT_TABLE, vpnName, NatUtil.getVpnId(dataBroker, routerId.getValue()), externalIp, vpnService, fibService, bgpManager, dataBroker, LOG);\r
+ }\r
+ } else {\r
+ LOG.warn("NAT Service : No ipMapping present fot the routerId {}", routerId);\r
+ }\r
+\r
+ long vpnId = NatUtil.getVpnId(dataBroker, vpnName);\r
+ // Install 47 entry to point to 21\r
+ if(vpnId != -1) {\r
+ LOG.debug("NAT Service : Calling externalRouterListener installNaptPfibEntry for donId {} and vpnId {}", dpnId, vpnId);\r
+ externalRouterListener.installNaptPfibEntry(dpnId, vpnId);\r
+ }\r
+\r
+ }\r
+\r
+ }\r
+\r
+ private void disassociateExternalNetworkFromVPN(Networks network, String vpnName) {\r
+ List<Uuid> routerIds = network.getRouterIds();\r
+\r
+ //long vpnId = NatUtil.getVpnId(dataBroker, vpnName);\r
+ for(Uuid routerId : routerIds) {\r
+ //long router = NatUtil.getVpnId(dataBroker, routerId.getValue());\r
+\r
+ InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerId.getValue());\r
+ Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);\r
+ if(!optRouterPorts.isPresent()) {\r
+ LOG.debug("Could not read Router Ports data object with id: {} to handle disassociate ext nw {}", routerId, network.getId());\r
+ continue;\r
+ }\r
+ RouterPorts routerPorts = optRouterPorts.get();\r
+ List<Ports> interfaces = routerPorts.getPorts();\r
+ for(Ports port : interfaces) {\r
+ String portName = port.getPortName();\r
+ BigInteger dpnId = getDpnForInterface(interfaceManager, portName);\r
+ if(dpnId.equals(BigInteger.ZERO)) {\r
+ LOG.debug("DPN not found for {}, skip handling of ext nw {} disassociation", portName, network.getId());\r
+ continue;\r
+ }\r
+ List<IpMapping> ipMapping = port.getIpMapping();\r
+ for(IpMapping ipMap : ipMapping) {\r
+ String externalIp = ipMap.getExternalIp();\r
+ floatingIpListener.removeNATFlowEntries(dpnId, portName, vpnName, routerId.getValue(), network.getId(), ipMap.getInternalIp(), externalIp);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {\r
+ BigInteger nodeId = BigInteger.ZERO;\r
+ try {\r
+ GetDpidFromInterfaceInput\r
+ dpIdInput =\r
+ new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();\r
+ Future<RpcResult<GetDpidFromInterfaceOutput>>\r
+ dpIdOutput =\r
+ interfaceManagerRpcService.getDpidFromInterface(dpIdInput);\r
+ RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();\r
+ if (dpIdResult.isSuccessful()) {\r
+ nodeId = dpIdResult.getResult().getDpid();\r
+ } else {\r
+ LOG.error("Could not retrieve DPN Id for interface {}", ifName);\r
+ }\r
+ } catch (InterruptedException | ExecutionException e) {\r
+ LOG.error("Exception when getting dpn for interface {}", ifName, e);\r
+ }\r
+ return nodeId;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*
+ * Copyright (c) 2015 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.natservice.internal;
+
+import java.math.BigInteger;
+import java.util.*;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.bgpmanager.api.IBgpManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.FibRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.IntextIpPortMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ProtocolTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.VpnRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.IpPortMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.ip.port.map.IpPortExternal;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.GenerateVpnLabelOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.GenerateVpnLabelInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.GenerateVpnLabelInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.CreateFibEntryInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.CreateFibEntryInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.RemoveFibEntryInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.RemoveVpnLabelInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.RemoveFibEntryInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.RemoveVpnLabelInputBuilder;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.datastoreutils.AsyncDataTreeChangeListenerBase;
+import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.ActionType;
+import org.opendaylight.vpnservice.mdsalutil.BucketInfo;
+import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
+import org.opendaylight.vpnservice.mdsalutil.GroupEntity;
+import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
+import org.opendaylight.vpnservice.mdsalutil.InstructionType;
+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.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+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.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
+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;
+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.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.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ExtRouters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.NaptSwitches;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.RouterIdName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ext.routers.Routers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ext.routers.RoutersKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.router.id.name.RouterIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.router.id.name.RouterIdsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.router.id.name.RouterIdsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.Subnetmaps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.Subnetmap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+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 com.google.common.base.Optional;
+import com.google.common.collect.Sets;
+import com.google.common.collect.Sets.SetView;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Created by EYUGSAR on 2/20/2016.
+ */
+
+public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Routers, ExternalRoutersListener>{
+
+ private static final Logger LOG = LoggerFactory.getLogger( ExternalRoutersListener.class);
+ private static long label;
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker dataBroker;
+ private IMdsalApiManager mdsalManager;
+ private ItmRpcService itmManager;
+ private OdlInterfaceRpcService interfaceManager;
+ private IdManagerService idManager;
+ private NaptManager naptManager;
+ private NAPTSwitchSelector naptSwitchSelector;
+ private IBgpManager bgpManager;
+ private VpnRpcService vpnService;
+ private FibRpcService fibService;
+ private SNATDefaultRouteProgrammer defaultRouteProgrammer;
+ private static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
+ static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000022", 16);
+ private NaptEventHandler naptEventHandler;
+ private NaptPacketInHandler naptPacketInHandler;
+
+ public void setNaptEventHandler(NaptEventHandler naptEventHandler) {
+ this.naptEventHandler = naptEventHandler;
+ }
+
+ public void setNaptPacketInHandler(NaptPacketInHandler naptPacketInHandler) {
+ this.naptPacketInHandler = naptPacketInHandler;
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ public void setItmManager(ItmRpcService itmManager) {
+ this.itmManager = itmManager;
+ }
+
+ public void setIdManager(IdManagerService idManager) {
+ this.idManager = idManager;
+ createGroupIdPool();
+ }
+
+ void setDefaultProgrammer(SNATDefaultRouteProgrammer defaultRouteProgrammer) {
+ this.defaultRouteProgrammer = defaultRouteProgrammer;
+ }
+
+
+ public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
+ this.interfaceManager = interfaceManager;
+ }
+
+ public void setNaptManager(NaptManager naptManager) {
+ this.naptManager = naptManager;
+ }
+
+ public void setNaptSwitchSelector(NAPTSwitchSelector naptSwitchSelector) {
+ this.naptSwitchSelector = naptSwitchSelector;
+ }
+
+ public void setBgpManager(IBgpManager bgpManager) {
+ this.bgpManager = bgpManager;
+ }
+
+ public void setVpnService(VpnRpcService vpnService) {
+ this.vpnService = vpnService;
+ }
+
+ public void setFibService(FibRpcService fibService) {
+ this.fibService = fibService;
+ }
+
+ public ExternalRoutersListener(DataBroker dataBroker )
+ {
+ super( Routers.class, ExternalRoutersListener.class );
+ this.dataBroker = dataBroker;
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Routers> identifier, Routers routers) {
+
+ LOG.info( "NAT Service : Add external router event for {}", routers.getRouterName() );
+
+ LOG.info("Installing NAT default route on all dpns part of router {}", routers.getRouterName());
+ addOrDelDefFibRouteToSNAT(routers.getRouterName(), true);
+
+ if( !routers.isEnableSnat()) {
+ LOG.info( "SNAT is disabled for external router {} ", routers.getRouterName());
+ return;
+ }
+
+ // Populate the router-id-name container
+ String routerName = routers.getRouterName();
+ Long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(routerId)).setRouterId(routerId).setRouterName(routerName).build();
+ MDSALUtil.syncWrite( dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(routerId), rtrs);
+
+ handleEnableSnat(routers);
+ }
+
+ public void handleEnableSnat(Routers routers){
+ String routerName = routers.getRouterName();
+ LOG.info("NAT Service : Handling SNAT for router {}", routerName);
+
+ long segmentId = NatUtil.getVpnId(dataBroker, routerName);
+ naptManager.initialiseExternalCounter(routers, segmentId);
+
+ // Allocate Primary Napt Switch for this router
+ BigInteger primarySwitchId = naptSwitchSelector.selectNewNAPTSwitch(routerName);
+ LOG.debug("NAT Service : Primary NAPT switch DPN ID {}", primarySwitchId);
+ if(primarySwitchId == null || primarySwitchId.equals(BigInteger.ZERO)){
+ LOG.error("NAT Service : Unable to to select the primary NAPT switch");
+ }
+ LOG.debug("NAT Service : About to create and install outbound miss entry in Primary Switch {} for router {}", primarySwitchId, routerName);
+
+ long bgpVpnId = NatConstants.INVALID_ID;
+ Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
+ if(bgpVpnUuid != null){
+ bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
+ }
+ if(bgpVpnId != NatConstants.INVALID_ID){
+
+ String bgpVpnName = bgpVpnUuid.getValue();
+ LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
+ RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(bgpVpnId)).setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
+ MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(bgpVpnId), rtrs);
+
+ long groupId = 0;
+ long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ List<BigInteger> switches = NatUtil.getDpnsForRouter(dataBroker, routerName);
+ if(switches == null){
+ LOG.error("NAT Service : No DPNS associated for the router {}", routerName);
+ return;
+ }
+ for (BigInteger dpnId : switches) {
+ // Handle switches and NAPT switches separately
+ if (!dpnId.equals(primarySwitchId)) {
+ LOG.debug("NAT Service : Install group in Ordinary switch {}", dpnId);
+ List<BucketInfo> bucketInfoForNonNaptSwitches = getBucketInfoForNonNaptSwitches(dpnId, primarySwitchId, routerName);
+ groupId = installGroup(dpnId, routerName, bucketInfoForNonNaptSwitches);
+ }else{
+ LOG.debug("NAT Service : Install group in Primary switch {}", dpnId);
+ List<BucketInfo> bucketInfoForNaptSwitches = getBucketInfoForPrimaryNaptSwitch();
+ groupId = installGroup(dpnId, routerName, bucketInfoForNaptSwitches);
+
+ Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
+ //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
+ if(vpnId != null && vpnId != NatConstants.INVALID_ID) {
+ installNaptPfibEntry(dpnId, vpnId);
+ }
+
+ }
+ installFlowsWithUpdatedVpnId(primarySwitchId, routerName, groupId, bgpVpnId, routerId);
+ }
+ }else {
+ // write metadata and punt
+ installOutboundMissEntry(routerName, primarySwitchId);
+ // Now install entries in SNAT tables to point to Primary for each router
+ List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
+ for (BigInteger dpnId : switches) {
+ // Handle switches and NAPT switches separately
+ if (!dpnId.equals(primarySwitchId)) {
+ LOG.debug("NAT Service : Handle Ordinary switch");
+ handleSwitches(dpnId, routerName, primarySwitchId);
+ } else {
+ LOG.debug("NAT Service : Handle NAPT switch");
+ handlePrimaryNaptSwitch(dpnId, routerName, primarySwitchId);
+ }
+ }
+ }
+
+ // call registerMapping Api
+ LOG.debug("NAT Service : Preparing to call registerMapping for routerName {} and Id {}", routerName, segmentId);
+
+ List<Uuid> subnetList = null;
+ List<String> externalIps = null;
+
+ InstanceIdentifier<Routers> id = InstanceIdentifier
+ .builder(ExtRouters.class)
+ .child(Routers.class, new RoutersKey(routerName))
+ .build();
+
+ Optional<Routers> extRouters = read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+
+ if(extRouters.isPresent())
+ {
+ LOG.debug("NAT Service : Fetching values from extRouters model");
+ Routers routerEntry= extRouters.get();
+ subnetList = routerEntry.getSubnetIds();
+ externalIps = routerEntry.getExternalIps();
+ int counter = 0;
+ int extIpCounter = externalIps.size();
+ LOG.debug("NAT Service : counter values before looping counter {} and extIpCounter {}", counter, extIpCounter);
+ for(Uuid subnet : subnetList) {
+ LOG.debug("NAT Service : Looping internal subnets for subnet {}", subnet);
+ InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
+ .builder(Subnetmaps.class)
+ .child(Subnetmap.class, new SubnetmapKey(subnet))
+ .build();
+ Optional<Subnetmap> sn = read(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetmapId);
+ if(sn.isPresent()){
+ // subnets
+ Subnetmap subnetmapEntry = sn.get();
+ String subnetString = subnetmapEntry.getSubnetIp();
+ String[] subnetSplit = subnetString.split("/");
+ String subnetIp = subnetSplit[0];
+ String subnetPrefix = "0";
+ if(subnetSplit.length == 2) {
+ subnetPrefix = subnetSplit[1];
+ }
+ IPAddress subnetAddr = new IPAddress(subnetIp, Integer.parseInt(subnetPrefix));
+ LOG.debug("NAT Service : subnetAddr is {} and subnetPrefix is {}", subnetAddr.getIpAddress(), subnetAddr.getPrefixLength());
+ //externalIps
+ LOG.debug("NAT Service : counter values counter {} and extIpCounter {}", counter, extIpCounter);
+ if(extIpCounter != 0) {
+ if(counter < extIpCounter) {
+ String[] IpSplit = externalIps.get(counter).split("/");
+ String externalIp = IpSplit[0];
+ String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
+ if(IpSplit.length==2) {
+ extPrefix = IpSplit[1];
+ }
+ IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
+ LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
+ naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
+ LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
+ externalIp, extPrefix);
+
+ String externalIpAddrPrefix = externalIpAddr.getIpAddress() + "/" + externalIpAddr.getPrefixLength();
+ LOG.debug("NAT Service : Calling handleSnatReverseTraffic for primarySwitchId {}, routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
+ handleSnatReverseTraffic(primarySwitchId, segmentId, externalIpAddrPrefix);
+
+ } else {
+ counter = 0; //Reset the counter which runs on externalIps for round-robbin effect
+ LOG.debug("NAT Service : Counter on externalIps got reset");
+ String[] IpSplit = externalIps.get(counter).split("/");
+ String externalIp = IpSplit[0];
+ String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
+ if(IpSplit.length==2) {
+ extPrefix = IpSplit[1];
+ }
+ IPAddress externalIpAddr = new IPAddress(externalIp, Integer.parseInt(extPrefix));
+ LOG.debug("NAT Service : externalIp is {} and extPrefix is {}", externalIpAddr.getIpAddress(), externalIpAddr.getPrefixLength());
+ naptManager.registerMapping(segmentId, subnetAddr, externalIpAddr);
+ LOG.debug("NAT Service : Called registerMapping for subnetIp {}, prefix {}, externalIp {}. prefix {}", subnetIp, subnetPrefix,
+ externalIp, extPrefix);
+
+ String externalIpAddrPrefix = externalIpAddr.getIpAddress() + "/" + externalIpAddr.getPrefixLength();
+ LOG.debug("NAT Service : Calling handleSnatReverseTraffic for primarySwitchId {}, routerName {} and externalIpAddPrefix {}", primarySwitchId, routerName, externalIpAddrPrefix);
+ handleSnatReverseTraffic(primarySwitchId, segmentId, externalIpAddrPrefix);
+
+ }
+ }
+ counter++;
+ LOG.debug("NAT Service : Counter on externalIps incremented to {}", counter);
+
+ } else {
+ LOG.warn("NAT Service : No internal subnets present in extRouters Model");
+ }
+ }
+ }
+
+ LOG.info("NAT Service : handleEnableSnat() Exit");
+ }
+
+ private void addOrDelDefFibRouteToSNAT(String routerName, boolean create) {
+ //Check if BGP VPN exists. If exists then invoke the new method.
+ long bgpVpnId = NatUtil.getBgpVpnId(dataBroker, routerName);
+ if(bgpVpnId != NatConstants.INVALID_ID) {
+ addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, bgpVpnId, create);
+ return;
+ }
+
+ //Router ID is used as the internal VPN's name, hence the vrf-id in VpnInstance Op DataStore
+ addOrDelDefaultFibRouteForSNAT(routerName, create);
+/* InstanceIdentifier<VpnInstanceOpDataEntry> id = NatUtil.getVpnInstanceOpDataIdentifier(routerName);
+ Optional<VpnInstanceOpDataEntry> vpnInstOp = NatUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
+ if (vpnInstOp.isPresent()) {
+ addOrDelDefaultFibRouteForSNAT(routerName, create);
+ } *//*else {
+ //Check if this router is associated with any external VPN
+ LOG.debug("Checking if router {} is associated with BGP VPN", routerName);
+ Uuid vpnId = NatUtil.getVpnForRouter(dataBroker, routerName);
+ if(vpnId != null) {
+ String vpnName = vpnId.getValue();
+ LOG.debug("Router {} is associated with VPN {}", routerName, vpnName);
+ InstanceIdentifier<VpnInstanceOpDataEntry> vid = NatUtil.getVpnInstanceOpDataIdentifier(vpnName);
+ vpnInstOp = NatUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, vid);
+ if (vpnInstOp.isPresent()) {
+ addOrDelDefaultFibRouteForSNAT(routerName, vpnInstOp.get(), create);
+ }
+ }
+ }*/
+ }
+
+ private void addOrDelDefaultFibRouteForSNAT(String routerName, boolean create) {
+/*
+ List<VpnToDpnList> dpnListInVpn = vpnInstOp.getVpnToDpnList();
+ List<BigInteger> switches = new ArrayList<>();
+ if(dpnListInVpn == null || dpnListInVpn.isEmpty()) {
+ LOG.debug("NAT Service : Unable to get the switches for the router {} from the VPNInstanceOpData", routerName);
+ switches = NatUtil.getDpnsForRouter(dataBroker, routerName);
+ if(switches == null || switches.isEmpty()){
+ LOG.error("NAT Service : addOrDelDefaultFibRouteForSNAT : NO SWITCHES ARE PART OF ROUTER {}", routerName);
+ return;
+ }
+ }else{
+ for (VpnToDpnList dpn : dpnListInVpn) {
+ switches.add(dpn.getDpnId());
+ }
+ }
+*/
+ List<BigInteger> switches = naptSwitchSelector.getDpnsForVpn(routerName);
+ long routerId = NatUtil.readVpnId(dataBroker, routerName);
+ if(routerId == NatConstants.INVALID_ID) {
+ LOG.error("Could not retrieve router Id for {} to program default NAT route in FIB", routerName);
+ return;
+ }
+ for (BigInteger dpnId : switches) {
+ if (create == true) {
+ defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId);
+ } else {
+ defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId);
+ }
+ }
+ }
+
+ private void addOrDelDefaultFibRouteForSNATWIthBgpVpn(String routerName, long bgpVpnId, boolean create) {
+ List<BigInteger> dpnIds = NatUtil.getDpnsForRouter(dataBroker, routerName);
+ if(dpnIds == null || dpnIds.isEmpty()) {
+ LOG.debug("NAT Service : Current no dpns part of router {} to program default NAT route", routerName);
+ return;
+ }
+ long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ for (BigInteger dpnId : dpnIds) {
+ if (create == true) {
+ if(bgpVpnId != NatConstants.INVALID_ID) {
+ defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, bgpVpnId, routerId);
+ }else{
+ defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, routerId);
+ }
+ } else {
+ if(bgpVpnId != NatConstants.INVALID_ID) {
+ defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, bgpVpnId, routerId);
+ }else{
+ defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, routerId);
+ }
+ }
+ }
+ }
+
+ 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 void close() throws Exception
+ {
+ if (listenerRegistration != null)
+ {
+ try
+ {
+ listenerRegistration.close();
+ }
+ catch (final Exception e)
+ {
+ LOG.error("Error when cleaning up ExternalRoutersListener.", e);
+ }
+
+ listenerRegistration = null;
+ }
+ LOG.debug("ExternalRoutersListener Closed");
+ }
+
+ protected void installOutboundMissEntry(String routerName, BigInteger primarySwitchId) {
+ long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ LOG.debug("NAT Service : Router ID from getVpnId {}", routerId);
+ if(routerId != NatConstants.INVALID_ID) {
+ LOG.debug("NAT Service : Creating miss entry on primary {}, for router {}", primarySwitchId, routerId);
+ createOutboundTblEntry(primarySwitchId, routerId);
+ } else {
+ LOG.error("NAT Service : Unable to fetch Router Id for RouterName {}, failed to createAndInstallMissEntry", routerName);
+ }
+ }
+
+ public String getFlowRefOutbound(BigInteger dpnId, short tableId, long routerID) {
+ return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
+ append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
+ }
+
+ public BigInteger getCookieOutboundFlow(long routerId) {
+ return NatConstants.COOKIE_OUTBOUND_NAPT_TABLE.add(new BigInteger("0110001", 16)).add(
+ BigInteger.valueOf(routerId));
+ }
+
+ protected FlowEntity buildOutboundFlowEntity(BigInteger dpId, long routerId) {
+ LOG.debug("NAT Service : buildOutboundFlowEntity called for dpId {} and routerId{}", dpId, routerId);
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ BigInteger.valueOf(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
+
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+ actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
+ instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+ instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
+
+ String flowRef = getFlowRefOutbound(dpId, NatConstants.OUTBOUND_NAPT_TABLE, routerId);
+ BigInteger cookie = getCookieOutboundFlow(routerId);
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.OUTBOUND_NAPT_TABLE, flowRef,
+ 5, flowRef, 0, 0,
+ cookie, matches, instructions);
+ LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
+ return flowEntity;
+ }
+
+ public void createOutboundTblEntry(BigInteger dpnId, long routerId) {
+ LOG.debug("NAT Service : createOutboundTblEntry called for dpId {} and routerId {}", dpnId, routerId);
+ FlowEntity flowEntity = buildOutboundFlowEntity(dpnId, routerId);
+ LOG.debug("NAT Service : Installing flow {}", flowEntity);
+ mdsalManager.installFlow(flowEntity);
+ }
+
+ protected String getTunnelInterfaceName(BigInteger srcDpId, BigInteger dstDpId) {
+ Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
+ RpcResult<GetTunnelInterfaceNameOutput> rpcResult;
+ try {
+ Future<RpcResult<GetTunnelInterfaceNameOutput>> result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
+ .setSourceDpid(srcDpId)
+ .setDestinationDpid(dstDpId)
+// .setTunnelType(tunType)
+ .build());
+ rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ tunType = TunnelTypeGre.class ;
+ result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
+ .setSourceDpid(srcDpId)
+ .setDestinationDpid(dstDpId)
+// .setTunnelType(tunType)
+ .build());
+ rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
+ } else {
+ return rpcResult.getResult().getInterfaceName();
+ }
+ LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
+ } else {
+ return rpcResult.getResult().getInterfaceName();
+ }
+ } catch (InterruptedException | ExecutionException | NullPointerException e) {
+ LOG.warn("NAT Service : Exception when getting tunnel interface Id for tunnel between {} and {}", srcDpId, dstDpId);
+ }
+
+ return null;
+ }
+
+ protected List<ActionInfo> getEgressActionsForInterface(String ifName, long routerId) {
+ LOG.debug("NAT Service : getEgressActionsForInterface called for interface {}", ifName);
+ List<ActionInfo> listActionInfo = new ArrayList<ActionInfo>();
+ try {
+ Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
+ interfaceManager.getEgressActionsForInterface(
+ new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName).setTunnelKey(routerId).build());
+ RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to Get egress actions for interface {} returned with Errors {}", ifName, rpcResult.getErrors());
+ } else {
+ 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) {
+ 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) {
+ LOG.warn("Exception when egress actions for interface {}", ifName, e);
+ }
+ return listActionInfo;
+ }
+
+ protected void installSnatMissEntry(BigInteger dpnId, List<BucketInfo> bucketInfo, String routerName) {
+ LOG.debug("NAT Service : installSnatMissEntry called for dpnId {} with primaryBucket {} ", dpnId, bucketInfo.get(0));
+ // Install the select group
+ long groupId = createGroupId(getGroupIdKey(routerName));
+ GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, bucketInfo);
+ LOG.debug("NAT Service : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
+ mdsalManager.installGroup(groupEntity);
+ // Install miss entry pointing to group
+ FlowEntity flowEntity = buildSnatFlowEntity(dpnId, routerName, groupId);
+ mdsalManager.installFlow(flowEntity);
+ }
+
+ long installGroup(BigInteger dpnId, String routerName, List<BucketInfo> bucketInfo){
+ long groupId = createGroupId(getGroupIdKey(routerName));
+ GroupEntity groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, bucketInfo);
+ LOG.debug("NAT Service : installing the SNAT to NAPT GroupEntity:{}", groupEntity);
+ mdsalManager.installGroup(groupEntity);
+ return groupId;
+ }
+
+ public FlowEntity buildSnatFlowEntity(BigInteger dpId, String routerName, long groupId) {
+
+ LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} and groupId {}", dpId, routerName, groupId );
+ long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ BigInteger.valueOf(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
+
+
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ List<ActionInfo> actionsInfo = new ArrayList<ActionInfo>();
+
+ ActionInfo actionSetField = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
+ BigInteger.valueOf(routerId)}) ;
+ actionsInfo.add(actionSetField);
+ LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
+ actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
+ instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfo));
+ String flowRef = getFlowRefSnat(dpId, NatConstants.PSNAT_TABLE, routerName);
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
+ NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_SNAT_TABLE, matches, instructions);
+
+ LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
+ return flowEntity;
+ }
+
+ // TODO : Replace this with ITM Rpc once its available with full functionality
+ protected void installTerminatingServiceTblEntry(BigInteger dpnId, String routerName) {
+ LOG.debug("NAT Service : creating entry for Terminating Service Table for switch {}, routerName {}", dpnId, routerName);
+ FlowEntity flowEntity = buildTsFlowEntity(dpnId, routerName);
+ mdsalManager.installFlow(flowEntity);
+
+ }
+
+ private FlowEntity buildTsFlowEntity(BigInteger dpId, String routerName) {
+
+ BigInteger routerId = BigInteger.valueOf (NatUtil.getVpnId(dataBroker, routerName));
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+ matches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {routerId }));
+
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]
+ { routerId, MetaDataUtil.METADATA_MASK_VRFID }));
+ instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
+ { NatConstants.OUTBOUND_NAPT_TABLE }));
+ String flowRef = getFlowRefTs(dpId, NatConstants.TERMINATING_SERVICE_TABLE, routerId.longValue());
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.TERMINATING_SERVICE_TABLE, flowRef,
+ NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_TS_TABLE, matches, instructions);
+ return flowEntity;
+ }
+
+ public String getFlowRefTs(BigInteger dpnId, short tableId, long routerID) {
+ return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
+ append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
+ }
+
+ public static String getFlowRefSnat(BigInteger dpnId, short tableId, String routerID) {
+ return new StringBuilder().append(NatConstants.SNAT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
+ append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
+ }
+
+ private String getGroupIdKey(String routerName){
+ String groupIdKey = new String("snatmiss." + routerName);
+ return groupIdKey;
+ }
+
+ protected long createGroupId(String groupIdKey) {
+ AllocateIdInput getIdInput = new AllocateIdInputBuilder()
+ .setPoolName(NatConstants.SNAT_IDPOOL_NAME).setIdKey(groupIdKey)
+ .build();
+ try {
+ Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
+ RpcResult<AllocateIdOutput> rpcResult = result.get();
+ return rpcResult.getResult().getIdValue();
+ } catch (NullPointerException | InterruptedException | ExecutionException e) {
+ LOG.trace("",e);
+ }
+ return 0;
+ }
+
+ protected void createGroupIdPool() {
+ CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
+ .setPoolName(NatConstants.SNAT_IDPOOL_NAME)
+ .setLow(NatConstants.SNAT_ID_LOW_VALUE)
+ .setHigh(NatConstants.SNAT_ID_HIGH_VALUE)
+ .build();
+ try {
+ Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
+ if ((result != null) && (result.get().isSuccessful())) {
+ LOG.debug("NAT Service : Created GroupIdPool");
+ } else {
+ LOG.error("NAT Service : Unable to create GroupIdPool");
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Failed to create PortPool for NAPT Service",e);
+ }
+ }
+
+ protected void handleSwitches (BigInteger dpnId, String routerName, BigInteger primarySwitchId) {
+ LOG.debug("NAT Service : Installing SNAT miss entry in switch {}", dpnId);
+ List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
+ String ifNamePrimary = getTunnelInterfaceName( dpnId, primarySwitchId);
+ List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
+ long routerId = NatUtil.getVpnId(dataBroker, routerName);
+
+ if(ifNamePrimary != null) {
+ LOG.debug("NAT Service : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
+ listActionInfoPrimary = getEgressActionsForInterface(ifNamePrimary, routerId);
+ }
+ BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
+
+ listBucketInfo.add(0, bucketPrimary);
+ installSnatMissEntry(dpnId, listBucketInfo, routerName);
+
+ }
+ List<BucketInfo> getBucketInfoForNonNaptSwitches(BigInteger nonNaptSwitchId, BigInteger primarySwitchId, String routerName) {
+ List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
+ String ifNamePrimary = getTunnelInterfaceName(nonNaptSwitchId, primarySwitchId);
+ List<BucketInfo> listBucketInfo = new ArrayList<>();
+ long routerId = NatUtil.getVpnId(dataBroker, routerName);
+
+ if (ifNamePrimary != null) {
+ LOG.debug("NAT Service : On Non- Napt switch , Primary Tunnel interface is {}", ifNamePrimary);
+ listActionInfoPrimary = getEgressActionsForInterface(ifNamePrimary, routerId);
+ }
+ BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
+
+ listBucketInfo.add(0, bucketPrimary);
+ return listBucketInfo;
+ }
+ protected void handlePrimaryNaptSwitch (BigInteger dpnId, String routerName, BigInteger primarySwitchId) {
+
+ /*
+ * Primary NAPT Switch – bucket Should always point back to its own Outbound Table
+ */
+
+ LOG.debug("NAT Service : Installing SNAT miss entry in Primary NAPT switch {} ", dpnId);
+
+ List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
+ List<ActionInfo> listActionInfoPrimary = new ArrayList<ActionInfo>();
+ listActionInfoPrimary.add(new ActionInfo(ActionType.nx_resubmit, new String[]{String.valueOf(NatConstants.TERMINATING_SERVICE_TABLE)}));
+ BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
+ listBucketInfo.add(0, bucketPrimary);
+
+ long routerId = NatUtil.getVpnId(dataBroker, routerName);
+
+ installSnatMissEntry(dpnId, listBucketInfo, routerName);
+ installTerminatingServiceTblEntry(dpnId, routerName);
+ //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the router ID.
+ installNaptPfibEntry(dpnId, routerId);
+ Long vpnId = NatUtil.getVpnId(dataBroker, routerId);
+ //Install the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
+ if(vpnId != null && vpnId != NatConstants.INVALID_ID) {
+ installNaptPfibEntry(dpnId, vpnId);
+ }
+ }
+
+ List<BucketInfo> getBucketInfoForPrimaryNaptSwitch(){
+ List<BucketInfo> listBucketInfo = new ArrayList<>();
+ List<ActionInfo> listActionInfoPrimary = new ArrayList<>();
+ listActionInfoPrimary.add(new ActionInfo(ActionType.nx_resubmit, new String[]{String.valueOf(NatConstants.TERMINATING_SERVICE_TABLE)}));
+ BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
+ listBucketInfo.add(0, bucketPrimary);
+ return listBucketInfo;
+ }
+
+ public void installNaptPfibEntry(BigInteger dpnId, long segmentId) {
+ LOG.debug("NAT Service : installNaptPfibEntry called for dpnId {} and segmentId {} ", dpnId, segmentId);
+ FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntity(dpnId, segmentId);
+ mdsalManager.installFlow(naptPfibFlowEntity);
+ }
+
+ public FlowEntity buildNaptPfibFlowEntity(BigInteger dpId, long segmentId) {
+
+ LOG.debug("NAT Service : buildNaptPfibFlowEntity is called for dpId {}, segmentId {}", dpId, segmentId );
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ BigInteger.valueOf(segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
+
+ ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
+ ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
+ listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NatConstants.L3_FIB_TABLE) }));
+ instructionInfo.add(new InstructionInfo(InstructionType.apply_actions, listActionInfo));
+
+ String flowRef = getFlowRefTs(dpId, NatConstants.NAPT_PFIB_TABLE, segmentId);
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.NAPT_PFIB_TABLE, flowRef,
+ NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
+
+ LOG.debug("NAT Service : Returning NaptPFib Flow Entity {}", flowEntity);
+ return flowEntity;
+ }
+
+ private void handleSnatReverseTraffic(BigInteger dpnId, long routerId, String externalIp) {
+ LOG.debug("NAT Service : handleSnatReverseTraffic() entry for DPN ID, routerId, externalIp : {}", dpnId, routerId, externalIp);
+ Uuid networkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
+ if(networkId == null) {
+ LOG.error("NAT Service : networkId is null for the router ID {}", routerId);
+ return;
+ }
+ final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
+ if(vpnName == null) {
+ LOG.error("NAT Service : No VPN associated with ext nw {} to handle add external ip configuration {} in router {}",
+ networkId, externalIp, routerId);
+ return;
+ }
+ advToBgpAndInstallFibAndTsFlows(dpnId, NatConstants.INBOUND_NAPT_TABLE, vpnName, routerId, externalIp, vpnService, fibService, bgpManager, dataBroker, LOG);
+ LOG.debug("NAT Service : handleSnatReverseTraffic() exit for DPN ID, routerId, externalIp : {}", dpnId, routerId, externalIp);
+ }
+
+ public void advToBgpAndInstallFibAndTsFlows(final BigInteger dpnId, final short tableId, final String vpnName, final long routerId, final String externalIp,
+ VpnRpcService vpnService, final FibRpcService fibService, final IBgpManager bgpManager, final DataBroker dataBroker,
+ final Logger log){
+ LOG.debug("NAT Service : advToBgpAndInstallFibAndTsFlows() entry for DPN ID {}, tableId {}, vpnname {} and externalIp {}", dpnId, tableId, vpnName, externalIp);
+ //Generate VPN label for the external IP
+ GenerateVpnLabelInput labelInput = new GenerateVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
+ Future<RpcResult<GenerateVpnLabelOutput>> labelFuture = vpnService.generateVpnLabel(labelInput);
+
+ //On successful generation of the VPN label, advertise the route to the BGP and install the FIB routes.
+ ListenableFuture<RpcResult<Void>> future = Futures.transform(JdkFutureAdapters.listenInPoolThread(labelFuture), new AsyncFunction<RpcResult<GenerateVpnLabelOutput>, RpcResult<Void>>() {
+
+ @Override
+ public ListenableFuture<RpcResult<Void>> apply(RpcResult<GenerateVpnLabelOutput> result) throws Exception {
+ if (result.isSuccessful()) {
+ LOG.debug("NAT Service : inside apply with result success");
+ GenerateVpnLabelOutput output = result.getResult();
+ long label = output.getLabel();
+
+ //Inform BGP
+ String rd = NatUtil.getVpnRd(dataBroker, vpnName);
+ String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, dpnId);
+ NatUtil.addPrefixToBGP(bgpManager, rd, externalIp, nextHopIp, label, log);
+
+ //Get IPMaps from the DB for the router ID
+ List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
+ if (dbIpMaps != null) {
+ for (IpMap dbIpMap : dbIpMaps) {
+ String dbExternalIp = dbIpMap.getExternalIp();
+ //Select the IPMap, whose external IP is the IP for which FIB is installed
+ if (externalIp.equals(dbExternalIp)) {
+ String dbInternalIp = dbIpMap.getInternalIp();
+ IpMapKey dbIpMapKey = dbIpMap.getKey();
+ LOG.debug("Setting label {} for internalIp {} and externalIp {}", label, dbInternalIp, externalIp);
+ IpMap newIpm = new IpMapBuilder().setKey(dbIpMapKey).setInternalIp(dbInternalIp).setExternalIp(dbExternalIp).setLabel(label).build();
+ MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, naptManager.getIpMapIdentifier(routerId, dbInternalIp), newIpm);
+ break;
+ }
+ }
+ } else {
+ LOG.error("NAT Service : Failed to write label {} for externalIp {} for routerId {} in DS", label, externalIp, routerId);
+ }
+
+ //Install custom FIB routes
+ List<Instruction> customInstructions = new ArrayList<>();
+ customInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[]{tableId}).buildInstruction(0));
+ makeTunnelTableEntry(dpnId, label, customInstructions);
+ makeLFibTableEntry(dpnId, label, tableId);
+
+ CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId)
+ .setIpAddress(externalIp).setServiceId(label).setInstruction(customInstructions).build();
+ Future<RpcResult<Void>> future = fibService.createFibEntry(input);
+ return JdkFutureAdapters.listenInPoolThread(future);
+ } else {
+ LOG.error("NAT Service : inside apply with result failed");
+ String errMsg = String.format("Could not retrieve the label for prefix %s in VPN %s, %s", externalIp, vpnName, result.getErrors());
+ return Futures.immediateFailedFuture(new RuntimeException(errMsg));
+ }
+ }
+ });
+
+ Futures.addCallback(future, new FutureCallback<RpcResult<Void>>() {
+
+ @Override
+ public void onFailure(Throwable error) {
+ log.error("NAT Service : Error in generate label or fib install process", error);
+ }
+
+ @Override
+ public void onSuccess(RpcResult<Void> result) {
+ if (result.isSuccessful()) {
+ log.info("NAT Service : Successfully installed custom FIB routes for prefix {}", externalIp);
+ } else {
+ log.error("NAT Service : Error in rpc call to create custom Fib entries for prefix {} in DPN {}, {}", externalIp, dpnId, result.getErrors());
+ }
+ }
+ });
+ }
+
+ private void makeLFibTableEntry(BigInteger dpId, long serviceId, long tableId) {
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[]{0x8847L}));
+ matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
+
+ List<Instruction> instructions = new ArrayList<Instruction>();
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+ actionsInfos.add(new ActionInfo(ActionType.pop_mpls, new String[]{}));
+ Instruction writeInstruction = new InstructionInfo(InstructionType.apply_actions, actionsInfos).buildInstruction(0);
+ instructions.add(writeInstruction);
+ instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]{tableId}).buildInstruction(1));
+
+ // Install the flow entry in L3_LFIB_TABLE
+ String flowRef = getFlowRef(dpId, NwConstants.L3_LFIB_TABLE, serviceId, "");
+
+ Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
+ 10, flowRef, 0, 0,
+ COOKIE_VM_LFIB_TABLE, matches, instructions);
+
+ mdsalManager.installFlow(dpId, flowEntity);
+
+ LOG.debug("NAT Service : LFIB Entry for dpID {} : label : {} modified successfully {}",dpId, serviceId );
+ }
+
+ private void makeTunnelTableEntry(BigInteger dpnId, long serviceId, List<Instruction> customInstructions) {
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+
+ LOG.debug("NAT Service : Create terminatingServiceAction on DpnId = {} and serviceId = {} and actions = {}", dpnId , serviceId);
+
+ mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
+
+ Flow terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
+ getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""), 5, String.format("%s:%d", "TST Flow Entry ", serviceId),
+ 0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, customInstructions);
+
+ mdsalManager.installFlow(dpnId, terminatingServiceTableFlowEntity);
+ }
+
+ protected InstanceIdentifier<RouterIds> getRoutersIdentifier(long routerId) {
+ InstanceIdentifier<RouterIds> id = InstanceIdentifier.builder(
+ RouterIdName.class).child(RouterIds.class, new RouterIdsKey(routerId)).build();
+ return id;
+ }
+
+ private String getFlowRef(BigInteger dpnId, short tableId, long id, String ipAddress) {
+ return new StringBuilder(64).append(NatConstants.SNAT_FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
+ .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
+ .append(id).append(NwConstants.FLOWID_SEPARATOR).append(ipAddress).toString();
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Routers> identifier, Routers original, Routers update) {
+ String routerName = original.getRouterName();
+ Long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ BigInteger dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
+ Uuid networkId = original.getNetworkId();
+
+ // Check if its update on SNAT flag
+ boolean originalSNATEnabled = original.isEnableSnat();
+ boolean updatedSNATEnabled = update.isEnableSnat();
+ LOG.debug("NAT Service : update of externalRoutersListener called with originalFlag and updatedFlag as {} and {}", originalSNATEnabled, updatedSNATEnabled);
+ if(originalSNATEnabled != updatedSNATEnabled) {
+ if(originalSNATEnabled) {
+ //SNAT disabled for the router
+ Uuid networkUuid = original.getNetworkId();
+ LOG.info("NAT Service : SNAT disabled for Router {}", routerName);
+ if (routerId == NatConstants.INVALID_ID) {
+ LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerName);
+ return;
+ }
+ List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,routerId);
+ handleDisableSnat(routerName, networkUuid, externalIps, false, null);
+ } else {
+ LOG.info("NAT Service : SNAT enabled for Router {}", original.getRouterName());
+ handleEnableSnat(original);
+ }
+ }
+
+ //Check if the Update is on External IPs
+ LOG.debug("NAT Service : Checking if this is update on External IPs");
+ List<String> originalExternalIpsList = original.getExternalIps();
+ List<String> updatedExternalIpsList = update.getExternalIps();
+ Set<String> originalExternalIps = Sets.newHashSet(originalExternalIpsList);
+ Set<String> updatedExternalIps = Sets.newHashSet(updatedExternalIpsList);
+
+ //Check if the External IPs are added during the update.
+ SetView<String> addedExternalIps = Sets.difference(updatedExternalIps, originalExternalIps);
+ if(addedExternalIps.size() != 0) {
+ LOG.debug("NAT Service : Start processing of the External IPs addition during the update operation");
+ for (String addedExternalIp : addedExternalIps) {
+ /*
+ 1) Do nothing in the IntExtIp model.
+ 2) Initialise the count of the added external IP to 0 in the ExternalCounter model.
+ */
+ String[] externalIpParts = NatUtil.getExternalIpAndPrefix(addedExternalIp);
+ String externalIp = externalIpParts[0];
+ String externalIpPrefix = externalIpParts[1];
+ String externalpStr = externalIp + "/" + externalIpPrefix;
+ LOG.debug("NAT Service : Initialise the count mapping of the external IP {} for the router ID {} in the ExternalIpsCounter model.",
+ externalpStr, routerId);
+ naptManager.initialiseNewExternalIpCounter(routerId, externalpStr);
+ }
+ LOG.debug("NAT Service : End processing of the External IPs addition during the update operation");
+ }
+
+ //Check if the External IPs are removed during the update.
+ SetView<String> removedExternalIps = Sets.difference(originalExternalIps, updatedExternalIps);
+ if(removedExternalIps.size() > 0) {
+ LOG.debug("NAT Service : Start processing of the External IPs removal during the update operation");
+ List<String> removedExternalIpsAsList = new ArrayList<>();
+ for (String removedExternalIp : removedExternalIps) {
+ /*
+ 1) Remove the mappings in the IntExt IP model which has external IP.
+ 2) Remove the external IP in the ExternalCounter model.
+ 3) For the corresponding subnet IDs whose external IP mapping was removed, allocate one of the least loaded external IP.
+ Store the subnet IP and the reallocated external IP mapping in the IntExtIp model.
+ 4) Increase the count of the allocated external IP by one.
+ 5) Advertise to the BGP if external IP is allocated for the first time for the router i.e. the route for the external IP is absent.
+ 6) Remove the NAPT translation entries from Inbound and Outbound NAPT tables for the removed external IPs and also from the model.
+ 7) Advertise to the BGP for removing the route for the removed external IPs.
+ */
+
+ String[] externalIpParts = NatUtil.getExternalIpAndPrefix(removedExternalIp);
+ String externalIp = externalIpParts[0];
+ String externalIpPrefix = externalIpParts[1];
+ String externalIpAddrStr = externalIp + "/" + externalIpPrefix;
+
+ LOG.debug("NAT Service : Clear the routes from the BGP and remove the FIB and TS entries for removed external IP {}", externalIpAddrStr);
+ Uuid vpnUuId = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
+ String vpnName = "";
+ if(vpnUuId != null){
+ vpnName = vpnUuId.getValue();
+ }
+ clrRtsFromBgpAndDelFibTs(dpnId, routerId, externalIpAddrStr, vpnName);
+
+ LOG.debug("NAT Service : Remove the mappings in the IntExtIP model which has external IP.");
+ //Get the internal IPs which are associated to the removed external IPs
+ List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
+ List<String> removedInternalIps = new ArrayList<>();
+ for(IpMap ipMap : ipMaps){
+ if(ipMap.getExternalIp().equals(externalIpAddrStr)){
+ removedInternalIps.add(ipMap.getInternalIp());
+ }
+ }
+
+ LOG.debug("Remove the mappings of the internal IPs from the IntExtIP model.");
+ for(String removedInternalIp : removedInternalIps){
+ LOG.debug("NAT Service : Remove the IP mapping of the internal IP {} for the router ID {} from the IntExtIP model",
+ removedInternalIp, routerId);
+ naptManager.removeFromIpMapDS(routerId, removedInternalIp);
+ }
+
+ LOG.debug("NAT Service : Remove the count mapping of the external IP {} for the router ID {} from the ExternalIpsCounter model.",
+ externalIpAddrStr, routerId );
+ naptManager.removeExternalIpCounter(routerId, externalIpAddrStr);
+ removedExternalIpsAsList.add(externalIpAddrStr);
+
+ LOG.debug("NAT Service : Allocate the least loaded external IPs to the subnets whose external IPs were removed.");
+ for(String removedInternalIp : removedInternalIps) {
+ allocateExternalIp(dpnId, routerId, networkId, removedInternalIp);
+ }
+
+ LOG.debug("NAT Service : Remove the NAPT translation entries from Inbound and Outbound NAPT tables for the removed external IPs.");
+ //Get the internalIP and internal Port which were associated to the removed external IP.
+ List<Integer> externalPorts = new ArrayList<>();
+ Map<ProtocolTypes, List<String>> protoTypesIntIpPortsMap = new HashMap<>();
+ InstanceIdentifier<IpPortMapping> ipPortMappingId = InstanceIdentifier.builder(IntextIpPortMap.class)
+ .child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
+ Optional<IpPortMapping> ipPortMapping = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, ipPortMappingId);
+ if (ipPortMapping.isPresent()) {
+ List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.get().getIntextIpProtocolType();
+ for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
+ ProtocolTypes protoType = intextIpProtocolType.getProtocol();
+ List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
+ for(IpPortMap ipPortMap : ipPortMaps){
+ IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
+ if(ipPortExternal.getIpAddress().equals(externalIp)){
+ externalPorts.add(ipPortExternal.getPortNum());
+ List<String> removedInternalIpPorts = protoTypesIntIpPortsMap.get(protoType);
+ if(removedInternalIpPorts != null){
+ removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
+ protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
+ }else{
+ removedInternalIpPorts = new ArrayList<>();
+ removedInternalIpPorts.add(ipPortMap.getIpPortInternal());
+ protoTypesIntIpPortsMap.put(protoType, removedInternalIpPorts);
+ }
+ }
+ }
+ }
+ }
+
+ //Remove the IP port map from the intext-ip-port-map model, which were containing the removed external IP.
+ Set<Map.Entry<ProtocolTypes, List<String>>> protoTypesIntIpPorts = protoTypesIntIpPortsMap.entrySet();
+ Map<String, List<String>> internalIpPortMap = new HashMap<>();
+ for(Map.Entry protoTypesIntIpPort : protoTypesIntIpPorts){
+ ProtocolTypes protocolType = (ProtocolTypes)protoTypesIntIpPort.getKey();
+ List<String> removedInternalIpPorts = (List<String>)protoTypesIntIpPort.getValue();
+ for(String removedInternalIpPort : removedInternalIpPorts){
+ //Remove the IP port map from the intext-ip-port-map model, which were containing the removed external IP
+ naptManager.removeFromIpPortMapDS(routerId, removedInternalIpPort, protocolType);
+ //Remove the IP port incomint packer map.
+ naptPacketInHandler.removeIncomingPacketMap(removedInternalIpPort);
+ String[] removedInternalIpPortParts = removedInternalIpPort.split(":");
+ if(removedInternalIpPortParts.length == 2){
+ String removedInternalIp = removedInternalIpPortParts[0];
+ String removedInternalPort = removedInternalIpPortParts[1];
+ List<String> removedInternalPortsList = internalIpPortMap.get(removedInternalPort);
+ if (removedInternalPortsList != null){
+ removedInternalPortsList.add(removedInternalPort);
+ internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
+ }else{
+ removedInternalPortsList = new ArrayList<>();
+ removedInternalPortsList.add(removedInternalPort);
+ internalIpPortMap.put(removedInternalIp, removedInternalPortsList);
+ }
+ }
+ }
+ }
+
+ // Delete the entry from SnatIntIpPortMap DS
+ Set<String> internalIps = internalIpPortMap.keySet();
+ for(String internalIp : internalIps){
+ LOG.debug("NAT Service : Removing IpPort having the internal IP {} from the model SnatIntIpPortMap", internalIp);
+ naptManager.removeFromSnatIpPortDS(routerId, internalIp);
+ }
+
+ naptManager.removeNaptPortPool(externalIp);
+
+ LOG.debug("Remove the NAPT translation entries from Inbound NAPT tables for the removed external IP {}", externalIp);
+ for(Integer externalPort : externalPorts) {
+ //Remove the NAPT translation entries from Inbound NAPT table
+ naptEventHandler.removeNatFlows(dpnId, NatConstants.INBOUND_NAPT_TABLE, routerId, externalIp, externalPort);
+ }
+
+ Set<Map.Entry<String, List<String>>> internalIpPorts = internalIpPortMap.entrySet();
+ for(Map.Entry<String, List<String>> internalIpPort : internalIpPorts) {
+ String internalIp = internalIpPort.getKey();
+ LOG.debug("Remove the NAPT translation entries from Outbound NAPT tables for the removed internal IP {}", internalIp);
+ List<String> internalPorts = internalIpPort.getValue();
+ for(String internalPort : internalPorts){
+ //Remove the NAPT translation entries from Outbound NAPT table
+ naptEventHandler.removeNatFlows(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, routerId, internalIp, Integer.valueOf(internalPort));
+ }
+ }
+ }
+ LOG.debug("NAT Service : End processing of the External IPs removal during the update operation");
+ }
+
+ //Check if its Update on subnets
+ LOG.debug("NAT Service : Checking if this is update on subnets");
+ List<Uuid> originalSubnetIdsList = original.getSubnetIds();
+ List<Uuid> updatedSubnetIdsList = update.getSubnetIds();
+ Set<Uuid> originalSubnetIds = Sets.newHashSet(originalSubnetIdsList);
+ Set<Uuid> updatedSubnetIds = Sets.newHashSet(updatedSubnetIdsList);
+ SetView<Uuid> addedSubnetIds = Sets.difference(updatedSubnetIds, originalSubnetIds);
+
+ //Check if the Subnet IDs are added during the update.
+ if(addedSubnetIds.size() != 0){
+ LOG.debug("NAT Service : Start processing of the Subnet IDs addition during the update operation");
+ for(Uuid addedSubnetId : addedSubnetIds){
+ /*
+ 1) Select the least loaded external IP for the subnet and store the mapping of the subnet IP and the external IP in the IntExtIp model.
+ 2) Increase the count of the selected external IP by one.
+ 3) Advertise to the BGP if external IP is allocated for the first time for the router i.e. the route for the external IP is absent.
+ */
+ String subnetIp = NatUtil.getSubnetIp(dataBroker, addedSubnetId);
+ if(subnetIp != null) {
+ allocateExternalIp(dpnId, routerId, networkId, subnetIp);
+ }
+ }
+ LOG.debug("NAT Service : End processing of the Subnet IDs addition during the update operation");
+ }
+
+ //Check if the Subnet IDs are removed during the update.
+ SetView<Uuid> removedSubnetIds = Sets.difference(originalSubnetIds, updatedSubnetIds);
+ if(removedSubnetIds.size() != 0){
+ LOG.debug("NAT Service : Start processing of the Subnet IDs removal during the update operation");
+ for(Uuid removedSubnetId : removedSubnetIds){
+ String[] subnetAddr = NatUtil.getSubnetIpAndPrefix(dataBroker, removedSubnetId);
+ if(subnetAddr != null){
+ /*
+ 1) Remove the subnet IP and the external IP in the IntExtIp map
+ 2) Decrease the count of the coresponding external IP by one.
+ 3) Advertise to the BGP for removing the routes of the corresponding external IP if its not allocated to any other internal IP.
+ */
+ LOG.debug("NAT Service : Remove the IP mapping for the router ID {} and internal IP {}", routerId, subnetAddr[0]);
+ naptManager.removeFromIpMapDS(routerId, subnetAddr[0] + "/" + subnetAddr[1]);
+ }
+ }
+ LOG.debug("NAT Service : End processing of the Subnet IDs removal during the update operation");
+ }
+ }
+
+ private void allocateExternalIp(BigInteger dpnId, long routerId, Uuid networkId, String subnetIp){
+ String leastLoadedExtIpAddr = NatUtil.getLeastLoadedExternalIp(dataBroker, routerId);
+ if (leastLoadedExtIpAddr != null) {
+ String[] externalIpParts = NatUtil.getExternalIpAndPrefix(leastLoadedExtIpAddr);
+ String leastLoadedExtIp = externalIpParts[0];
+ String leastLoadedExtIpPrefix = externalIpParts[1];
+ String leastLoadedExtIpAddrStr = leastLoadedExtIp + "/" + leastLoadedExtIpPrefix;
+ IPAddress externalIpAddr = new IPAddress(leastLoadedExtIp, Integer.parseInt(leastLoadedExtIpPrefix));
+ String[] subnetIpParts = NatUtil.getSubnetIpAndPrefix(subnetIp);
+ subnetIp = subnetIpParts[0];
+ String subnetIpPrefix = subnetIpParts[1];
+ IPAddress subnetIpAddr = new IPAddress(subnetIp, Integer.parseInt(subnetIpPrefix));
+ LOG.debug("NAT Service : Add the IP mapping for the router ID {} and internal IP {} and prefix {} -> external IP {} and prefix {}",
+ routerId, subnetIp, subnetIpPrefix, leastLoadedExtIp, leastLoadedExtIpPrefix);
+ naptManager.registerMapping(routerId, subnetIpAddr, externalIpAddr);
+
+
+ //Check if external IP is already assigned a route. (i.e. External IP is previously allocated to any of the subnets)
+ //If external IP is already assigned a route, (, do not re-advertise to the BGP
+ if(checkExternalIpLabel(routerId, leastLoadedExtIpAddrStr)){
+ return;
+ }
+
+ //Re-advertise to the BGP for the external IP, which is allocated to the subnet for the first time and hence not having a route.
+ //Get the VPN Name using the network ID
+ final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
+ if (vpnName != null) {
+ LOG.debug("Retrieved vpnName {} for networkId {}", vpnName, networkId);
+ advToBgpAndInstallFibAndTsFlows(dpnId, NatConstants.INBOUND_NAPT_TABLE, vpnName, routerId,
+ leastLoadedExtIp + "/" + leastLoadedExtIpPrefix, vpnService, fibService, bgpManager, dataBroker, LOG);
+ }
+ }
+ }
+
+ private boolean checkExternalIpLabel(long routerId, String externalIp){
+ List<IpMap> ipMaps = naptManager.getIpMapList(dataBroker, routerId);
+ for(IpMap ipMap : ipMaps){
+ if(ipMap.getExternalIp().equals(externalIp)){
+ if (ipMap.getLabel() != null){
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Routers> identifier, Routers router) {
+ LOG.trace("NAT Service : Router delete method");
+ {
+ /*
+ ROUTER DELETE SCENARIO
+ 1) Get the router ID from the event.
+ 2) Build the cookie information from the router ID.
+ 3) Get the primary and secondary switch DPN IDs using the router ID from the model.
+ 4) Build the flow with the cookie value.
+ 5) Delete the flows which matches the cookie information from the NAPT outbound, inbound tables.
+ 6) Remove the flows from the other switches which points to the primary and secondary switches for the flows related the router ID.
+ 7) Get the list of external IP address maintained for the router ID.
+ 8) Use the NaptMananager removeMapping API to remove the list of IP addresses maintained.
+ 9) Withdraw the corresponding routes from the BGP.
+ */
+
+ if (identifier == null || router == null) {
+ LOG.info("++++++++++++++NAT Service : ExternalRoutersListener:remove:: returning without processing since routers is null");
+ return;
+ }
+
+ String routerName = router.getRouterName();
+ LOG.info("Removing default NAT route from FIB on all dpns part of router {} ", routerName);
+ addOrDelDefFibRouteToSNAT(routerName, false);
+ Uuid networkUuid = router.getNetworkId();
+ Long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ if (routerId == NatConstants.INVALID_ID) {
+ LOG.error("NAT Service : Invalid routerId returned for routerName {}", routerName);
+ return;
+ }
+ List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
+ handleDisableSnat(routerName, networkUuid, externalIps, true, null);
+ }
+ }
+
+ public void handleDisableSnat(String routerName, Uuid networkUuid, List<String> externalIps, boolean routerFlag, String vpnId){
+ LOG.info("NAT Service : handleDisableSnat() Entry");
+ try {
+ Long routerId = NatUtil.getVpnId(dataBroker, routerName);
+
+ BigInteger naptSwitchDpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
+ LOG.debug("NAT Service : got primarySwitch as dpnId{} ", naptSwitchDpnId);
+ if (naptSwitchDpnId == null || naptSwitchDpnId.equals(BigInteger.ZERO)){
+ LOG.error("NAT Service : Unable to retrieve the primary NAPT switch for the router ID {} from RouterNaptSwitch model", routerId);
+ return;
+ }
+ removeNaptFlowsFromActiveSwitch(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId );
+ removeFlowsFromNonActiveSwitches(routerName, naptSwitchDpnId, networkUuid);
+ try {
+ clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId);
+ } catch (Exception ex) {
+ LOG.debug("Failed to remove fib entries for routerId {} in naptSwitchDpnId {} : {}", routerId, naptSwitchDpnId,ex);
+ }
+
+ //Use the NaptMananager removeMapping API to remove the entire list of IP addresses maintained for the router ID.
+ LOG.debug("NAT Service : Remove the Internal to external IP address maintained for the router ID {} in the DS", routerId);
+ naptManager.removeMapping(routerId);
+
+ if(routerFlag) {
+ removeNaptSwitch(routerName);
+ } else {
+ updateNaptSwitch(routerName, BigInteger.ZERO);
+ }
+
+ LOG.debug("NAT Service : Remove the ExternalCounter model for the router ID {}", routerId);
+ naptManager.removeExternalCounter(routerId);
+ } catch (Exception ex) {
+ LOG.error("Exception while handling disableSNAT : {}", ex);
+ }
+ LOG.info("NAT Service : handleDisableSnat() Exit");
+ }
+
+ public void handleDisableSnatInternetVpn(String routerName, Uuid networkUuid, List<String> externalIps, boolean routerFlag, String vpnId){
+ LOG.debug("NAT Service : handleDisableSnatInternetVpn() Entry");
+ try {
+ Long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ BigInteger naptSwitchDpnId = null;
+ InstanceIdentifier<RouterToNaptSwitch> routerToNaptSwitch = NatUtil.buildNaptSwitchRouterIdentifier(routerName);
+ Optional<RouterToNaptSwitch> rtrToNapt = read(dataBroker, LogicalDatastoreType.OPERATIONAL, routerToNaptSwitch);
+ if (rtrToNapt.isPresent()) {
+ naptSwitchDpnId = rtrToNapt.get().getPrimarySwitchId();
+ }
+ LOG.debug("NAT Service : got primarySwitch as dpnId{} ", naptSwitchDpnId);
+
+ removeNaptFlowsFromActiveSwitchInternetVpn(routerId, routerName, naptSwitchDpnId, networkUuid, vpnId );
+ try {
+ clrRtsFromBgpAndDelFibTs(naptSwitchDpnId, routerId, networkUuid, externalIps, vpnId);
+ } catch (Exception ex) {
+ LOG.debug("Failed to remove fib entries for routerId {} in naptSwitchDpnId {} : {}", routerId, naptSwitchDpnId,ex);
+ }
+ } catch (Exception ex) {
+ LOG.error("Exception while handling disableSNATInternetVpn : {}", ex);
+ }
+ LOG.debug("NAT Service : handleDisableSnatInternetVpn() Exit");
+ }
+
+ public void updateNaptSwitch(String routerName, BigInteger naptSwitchId) {
+ RouterToNaptSwitch naptSwitch = new RouterToNaptSwitchBuilder().setKey(new RouterToNaptSwitchKey(routerName))
+ .setPrimarySwitchId(naptSwitchId).build();
+ try {
+ MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
+ NatUtil.buildNaptSwitchRouterIdentifier(routerName), naptSwitch);
+ } catch (Exception ex) {
+ LOG.error("Failed to write naptSwitch {} for router {} in ds",
+ naptSwitchId,routerName);
+ }
+ LOG.debug("Successfully updated naptSwitch {} for router {} in ds",
+ naptSwitchId,routerName);
+ }
+
+ protected void removeNaptSwitch(String routerName){
+ // Remove router and switch from model
+ InstanceIdentifier<RouterToNaptSwitch> id = InstanceIdentifier.builder(NaptSwitches.class).child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
+ LOG.debug("NAPT Service : Removing NaptSwitch and Router for the router {} from datastore", routerName);
+ MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
+ }
+
+ public void removeNaptFlowsFromActiveSwitch(long routerId, String routerName, BigInteger dpnId, Uuid networkId, String vpnName){
+
+ LOG.debug("NAT Service : Remove NAPT flows from Active switch");
+ BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
+
+ //Remove the PSNAT entry which forwards the packet to Terminating Service table
+ String pSNatFlowRef = getFlowRefSnat(dpnId, NatConstants.PSNAT_TABLE, routerName);
+ FlowEntity pSNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.PSNAT_TABLE, pSNatFlowRef);
+
+ LOG.info("NAT Service : Remove the flow in the " + NatConstants.PSNAT_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
+ mdsalManager.removeFlow(pSNatFlowEntity);
+
+ //Remove the group entry which resubmits the packet to the Terminating Service table or to the out port accordingly.
+ long groupId = createGroupId(getGroupIdKey(routerName));
+ List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
+ GroupEntity pSNatGroupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, listBucketInfo);
+
+ LOG.info("NAT Service : Remove the group {} for the active switch with the DPN ID {} and router ID {}", groupId, dpnId, routerId);
+ mdsalManager.removeGroup(pSNatGroupEntity);
+
+ //Remove the Terminating Service table entry which forwards the packet to Outbound NAPT Table
+ String tsFlowRef = getFlowRefTs(dpnId, NatConstants.TERMINATING_SERVICE_TABLE, routerId);
+ FlowEntity tsNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.TERMINATING_SERVICE_TABLE, tsFlowRef);
+
+ LOG.info("NAT Service : Remove the flow in the " + NatConstants.TERMINATING_SERVICE_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
+ mdsalManager.removeFlow(tsNatFlowEntity);
+
+ //Remove the Outbound flow entry which forwards the packet to FIB Table
+ String outboundNatFlowRef = getFlowRefOutbound(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, routerId);
+ FlowEntity outboundNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, outboundNatFlowRef);
+
+ LOG.info("NAT Service : Remove the flow in the " + NatConstants.OUTBOUND_NAPT_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
+ mdsalManager.removeFlow(outboundNatFlowEntity);
+
+ //Remove the NAPT PFIB TABLE which forwards the incoming packet to FIB Table matching on the router ID.
+ String natPfibFlowRef = getFlowRefTs(dpnId, NatConstants.NAPT_PFIB_TABLE, routerId);
+ FlowEntity natPfibFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.NAPT_PFIB_TABLE, natPfibFlowRef);
+
+ LOG.info("NAT Service : Remove the flow in the " + NatConstants.NAPT_PFIB_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
+ mdsalManager.removeFlow(natPfibFlowEntity);
+
+ //Long vpnId = NatUtil.getVpnId(dataBroker, routerId); - This does not work since ext-routers is deleted already - no network info
+ //Get the VPN ID from the ExternalNetworks model
+ long vpnId = -1;
+ if( (vpnName == null) || (vpnName.isEmpty()) ) {
+ // ie called from router delete cases
+ Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
+ LOG.debug("NAT Service : vpnUuid is {}", vpnUuid);
+ if(vpnUuid != null) {
+ vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
+ LOG.debug("NAT Service : vpnId for routerdelete or disableSNAT scenario {}", vpnId );
+ }
+ } else {
+ // ie called from disassociate vpn case
+ LOG.debug("NAT Service: This is disassociate nw with vpn case with vpnName {}", vpnName);
+ vpnId = NatUtil.getVpnId(dataBroker, vpnName);
+ LOG.debug("NAT Service : vpnId for disassociate nw with vpn scenario {}", vpnId );
+ }
+
+ if(vpnId != NatConstants.INVALID_ID){
+ //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
+ String natPfibVpnFlowRef = getFlowRefTs(dpnId, NatConstants.NAPT_PFIB_TABLE, vpnId);
+ FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
+ LOG.info("NAT Service : Remove the flow in the " + NatConstants.NAPT_PFIB_TABLE + " for the active switch with the DPN ID {} and VPN ID {}", dpnId, vpnId);
+ mdsalManager.removeFlow(natPfibVpnFlowEntity);
+ }
+
+ //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
+ IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
+ if(ipPortMapping == null){
+ LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
+ return;
+ }
+
+ List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
+ for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
+ List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
+ for(IpPortMap ipPortMap : ipPortMaps){
+ String ipPortInternal = ipPortMap.getIpPortInternal();
+ String[] ipPortParts = ipPortInternal.split(":");
+ if(ipPortParts.length != 2) {
+ LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
+ return;
+ }
+ String internalIp = ipPortParts[0];
+ String internalPort = ipPortParts[1];
+
+ //Build the flow for the outbound NAPT table
+ String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId), internalIp, Integer.valueOf(internalPort));
+ FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
+
+ LOG.info("NAT Service : Remove the flow in the " + NatConstants.OUTBOUND_NAPT_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
+ mdsalManager.removeFlow(outboundNaptFlowEntity);
+
+ IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
+ String externalIp = ipPortExternal.getIpAddress();
+ int externalPort = ipPortExternal.getPortNum();
+
+ //Build the flow for the inbound NAPT table
+ switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NatConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId), externalIp, externalPort);
+ FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
+
+ LOG.info("NAT Service : Remove the flow in the " + NatConstants.INBOUND_NAPT_TABLE + " for the active active switch with the DPN ID {} and router ID {}", dpnId, routerId);
+ mdsalManager.removeFlow(inboundNaptFlowEntity);
+ }
+ }
+ }
+
+ public void removeNaptFlowsFromActiveSwitchInternetVpn(long routerId, String routerName, BigInteger dpnId, Uuid networkId, String vpnName){
+
+ LOG.debug("NAT Service : Remove NAPT flows from Active switch Internet Vpn");
+ BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
+
+ //Remove the NAPT PFIB TABLE entry
+ long vpnId = -1;
+ if(vpnName != null) {
+ // ie called from disassociate vpn case
+ LOG.debug("NAT Service: This is disassociate nw with vpn case with vpnName {}", vpnName);
+ vpnId = NatUtil.getVpnId(dataBroker, vpnName);
+ LOG.debug("NAT Service : vpnId for disassociate nw with vpn scenario {}", vpnId );
+ }
+
+ if(vpnId != NatConstants.INVALID_ID){
+ //Remove the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table matching on the VPN ID.
+ String natPfibVpnFlowRef = getFlowRefTs(dpnId, NatConstants.NAPT_PFIB_TABLE, vpnId);
+ FlowEntity natPfibVpnFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.NAPT_PFIB_TABLE, natPfibVpnFlowRef);
+ LOG.info("NAT Service : Remove the flow in the " + NatConstants.NAPT_PFIB_TABLE + " for the active switch with the DPN ID {} and VPN ID {}", dpnId, vpnId);
+ mdsalManager.removeFlow(natPfibVpnFlowEntity);
+
+ // Remove IP-PORT active NAPT entries and release port from IdManager
+ //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
+ IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
+ if(ipPortMapping == null){
+ LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
+ return;
+ }
+ List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
+ for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
+ List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
+ for(IpPortMap ipPortMap : ipPortMaps){
+ String ipPortInternal = ipPortMap.getIpPortInternal();
+ String[] ipPortParts = ipPortInternal.split(":");
+ if(ipPortParts.length != 2) {
+ LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
+ return;
+ }
+ String internalIp = ipPortParts[0];
+ String internalPort = ipPortParts[1];
+
+ //Build the flow for the outbound NAPT table
+ String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId), internalIp, Integer.valueOf(internalPort));
+ FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
+
+ LOG.info("NAT Service : Remove the flow in the " + NatConstants.OUTBOUND_NAPT_TABLE + " for the active switch with the DPN ID {} and router ID {}", dpnId, routerId);
+ mdsalManager.removeFlow(outboundNaptFlowEntity);
+
+ IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
+ String externalIp = ipPortExternal.getIpAddress();
+ int externalPort = ipPortExternal.getPortNum();
+
+ //Build the flow for the inbound NAPT table
+ switchFlowRef = NatUtil.getNaptFlowRef(dpnId, NatConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId), externalIp, externalPort);
+ FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.INBOUND_NAPT_TABLE, cookieSnatFlow, switchFlowRef);
+
+ LOG.info("NAT Service : Remove the flow in the " + NatConstants.INBOUND_NAPT_TABLE + " for the active active switch with the DPN ID {} and router ID {}", dpnId, routerId);
+ mdsalManager.removeFlow(inboundNaptFlowEntity);
+
+ // Finally release port from idmanager
+ String internalIpPort = internalIp +":"+internalPort;
+ naptManager.removePortFromPool(internalIpPort, externalIp);
+
+ //Remove sessions from models
+ naptManager.removeIpPortMappingForRouterID(routerId);
+ naptManager.removeIntIpPortMappingForRouterID(routerId);
+ }
+ }
+ } else {
+ LOG.error("NAT Service : Invalid vpnId {}", vpnId);
+ }
+ }
+
+ public void removeFlowsFromNonActiveSwitches(String routerName, BigInteger naptSwitchDpnId, Uuid networkId){
+ LOG.debug("NAT Service : Remove NAPT related flows from non active switches");
+
+ //Remove the flows from the other switches which points to the primary and secondary switches for the flows related the router ID.
+ List<BigInteger> allSwitchList = naptSwitchSelector.getDpnsForVpn(routerName);
+ if(allSwitchList == null || allSwitchList.isEmpty()){
+ LOG.error("NAT Service : Unable to get the swithces for the router {}", routerName);
+ return;
+ }
+ Long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ for (BigInteger dpnId : allSwitchList) {
+ if (!naptSwitchDpnId.equals(dpnId)) {
+ LOG.info("NAT Service : Handle Ordinary switch");
+
+ //Remove the PSNAT entry which forwards the packet to Terminating Service table
+ String pSNatFlowRef = getFlowRefSnat(dpnId, NatConstants.PSNAT_TABLE, String.valueOf(routerName));
+ FlowEntity pSNatFlowEntity = NatUtil.buildFlowEntity(dpnId, NatConstants.PSNAT_TABLE, pSNatFlowRef);
+
+ LOG.info("Remove the flow in the " + NatConstants.PSNAT_TABLE + " for the non active switch with the DPN ID {} and router ID {}", dpnId, routerId);
+ mdsalManager.removeFlow(pSNatFlowEntity);
+
+ //Remove the group entry which resubmits the packet to the Terminating Service table or to the out port accordingly.
+ long groupId = createGroupId(getGroupIdKey(routerName));
+ List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
+ GroupEntity pSNatGroupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName, GroupTypes.GroupAll, listBucketInfo);
+
+ LOG.info("NAT Service : Remove the group {} for the non active switch with the DPN ID {} and router ID {}", groupId, dpnId, routerId);
+ mdsalManager.removeGroup(pSNatGroupEntity);
+
+ }
+ }
+ }
+
+ public void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, Long routerId, Uuid networkUuid, List<String> externalIps, String vpnName) {
+ //Withdraw the corresponding routes from the BGP.
+ //Get the network ID using the router ID.
+ LOG.debug("NAT Service : Advertise to BGP and remove routes for externalIps {} with routerId {}, network Id {} and vpnName {}",
+ externalIps,routerId,networkUuid, vpnName);
+ if(networkUuid == null ){
+ LOG.error("NAT Service : networkId is null");
+ return;
+ }
+
+ if (externalIps == null || externalIps.isEmpty()) {
+ LOG.debug("NAT Service : externalIps is null");
+ return;
+ }
+
+ if(vpnName ==null) {
+ //Get the VPN Name using the network ID
+ vpnName = NatUtil.getAssociatedVPN(dataBroker, networkUuid, LOG);
+ if (vpnName == null) {
+ LOG.error("No VPN associated with ext nw {} for the router {}",
+ networkUuid, routerId);
+ return;
+ }
+ }
+ LOG.debug("Retrieved vpnName {} for networkId {}",vpnName,networkUuid);
+
+ //Remove custom FIB routes
+ //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
+ for (String extIp : externalIps) {
+ clrRtsFromBgpAndDelFibTs(dpnId, routerId, extIp, vpnName);
+ }
+ }
+
+ private void clrRtsFromBgpAndDelFibTs(final BigInteger dpnId, long routerId, String extIp, final String vpnName){
+ //Inform BGP about the route removal
+ String rd = NatUtil.getVpnRd(dataBroker, vpnName);
+ NatUtil.removePrefixFromBGP(bgpManager, rd, extIp, LOG);
+
+ LOG.debug("Removing fib entry for externalIp {} in routerId {}",extIp,routerId);
+ //Get IPMaps from the DB for the router ID
+ List<IpMap> dbIpMaps = NaptManager.getIpMapList(dataBroker, routerId);
+ if (dbIpMaps == null || dbIpMaps.isEmpty()) {
+ LOG.error("NAT Service : IPMaps not found for router {}",routerId);
+ return;
+ }
+
+ long tempLabel = NatConstants.INVALID_ID;
+ for (IpMap dbIpMap : dbIpMaps) {
+ String dbExternalIp = dbIpMap.getExternalIp();
+ LOG.debug("Retrieved dbExternalIp {} for router id {}",dbExternalIp,routerId);
+ //Select the IPMap, whose external IP is the IP for which FIB is installed
+ if (extIp.equals(dbExternalIp)) {
+ tempLabel = dbIpMap.getLabel();
+ LOG.debug("Retrieved label {} for dbExternalIp {} with router id {}",tempLabel,dbExternalIp,routerId);
+ break;
+ }
+ }
+ if (tempLabel < 0 || tempLabel == NatConstants.INVALID_ID) {
+ LOG.error("NAT Service : Label not found for externalIp {} with router id {}",extIp,routerId);
+ return;
+ }
+
+ final long label = tempLabel;
+ final String externalIp = extIp;
+
+ RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label).build();
+ Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
+
+ ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future), new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
+
+ @Override
+ public ListenableFuture<RpcResult<Void>> apply(RpcResult<Void> result) throws Exception {
+ //Release label
+ if (result.isSuccessful()) {
+ removeTunnelTableEntry(dpnId, label);
+ removeLFibTableEntry(dpnId, label);
+ RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
+ Future<RpcResult<Void>> labelFuture = vpnService.removeVpnLabel(labelInput);
+ return JdkFutureAdapters.listenInPoolThread(labelFuture);
+ } else {
+ String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
+ LOG.error(errMsg);
+ return Futures.immediateFailedFuture(new RuntimeException(errMsg));
+ }
+ }
+
+ });
+
+ Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
+
+ @Override
+ public void onFailure(Throwable error) {
+ LOG.error("NAT Service : Error in removing the label or custom fib entries", error);
+ }
+
+ @Override
+ public void onSuccess(RpcResult<Void> result) {
+ if (result.isSuccessful()) {
+ LOG.debug("NAT Service : Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
+ } else {
+ LOG.error("NAT Service : Error in removing the label for prefix {} from VPN {}, {}", externalIp, vpnName, result.getErrors());
+ }
+ }
+ });
+ }
+
+ private void removeTunnelTableEntry(BigInteger dpnId, long serviceId) {
+ LOG.info("NAT Service : remove terminatingServiceActions called with DpnId = {} and label = {}", dpnId , serviceId);
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ // Matching metadata
+ mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
+ Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
+ getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""),
+ 5, String.format("%s:%d","TST Flow Entry ",serviceId), 0, 0,
+ COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, null);
+ mdsalManager.removeFlow(dpnId, flowEntity);
+ LOG.debug("NAT Service : Terminating service Entry for dpID {} : label : {} removed successfully {}",dpnId, serviceId);
+ }
+
+ private void removeLFibTableEntry(BigInteger dpnId, long serviceId) {
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x8847L }));
+ matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
+
+ String flowRef = getFlowRef(dpnId, NwConstants.L3_LFIB_TABLE, serviceId, "");
+
+ LOG.debug("NAT Service : removing LFib entry with flow ref {}", flowRef);
+
+ Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
+ 10, flowRef, 0, 0,
+ COOKIE_VM_LFIB_TABLE, matches, null);
+
+ mdsalManager.removeFlow(dpnId, flowEntity);
+
+ LOG.debug("NAT Service : LFIB Entry for dpID : {} label : {} removed successfully {}",dpnId, serviceId);
+ }
+
+ protected InstanceIdentifier<Routers> getWildCardPath()
+ {
+ return InstanceIdentifier.create(ExtRouters.class).child(Routers.class);
+ }
+
+
+ /**
+ * router association to vpn
+ *
+ */
+ public void changeLocalVpnIdToBgpVpnId(String routerName, String bgpVpnName){
+ LOG.debug("NAT Service : Router associated to BGP VPN");
+ if (chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
+ long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
+
+ LOG.debug("BGP VPN ID value {} ", bgpVpnId);
+
+ if(bgpVpnId != NatConstants.INVALID_ID){
+ LOG.debug("Populate the router-id-name container with the mapping BGP VPN-ID {} -> BGP VPN-NAME {}", bgpVpnId, bgpVpnName);
+ RouterIds rtrs = new RouterIdsBuilder().setKey(new RouterIdsKey(bgpVpnId)).setRouterId(bgpVpnId).setRouterName(bgpVpnName).build();
+ MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, getRoutersIdentifier(bgpVpnId), rtrs);
+
+ // Get the allocated Primary NAPT Switch for this router
+ long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ LOG.debug("Router ID value {} ", routerId);
+ BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
+
+ LOG.debug("NAT Service : Update the Router ID {} to the BGP VPN ID {} ", routerId, bgpVpnId);
+ addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, bgpVpnId, true);
+
+ // Get the group ID
+ long groupId = createGroupId(getGroupIdKey(routerName));
+ installFlowsWithUpdatedVpnId(primarySwitchId, routerName, groupId, bgpVpnId, routerId);
+ }
+ }
+ }
+
+ /**
+ * router disassociation from vpn
+ *
+ */
+ public void changeBgpVpnIdToLocalVpnId(String routerName, String bgpVpnName){
+ LOG.debug("NAT Service : Router dissociated from BGP VPN");
+ if(chkExtRtrAndSnatEnbl(new Uuid(routerName))) {
+ long bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnName);
+ LOG.debug("BGP VPN ID value {} ", bgpVpnId);
+
+ // Get the allocated Primary NAPT Switch for this router
+ long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ LOG.debug("Router ID value {} ", routerId);
+ BigInteger primarySwitchId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
+
+ LOG.debug("NAT Service : Update the BGP VPN ID {} to the Router ID {}", bgpVpnId, routerId);
+ addOrDelDefaultFibRouteForSNATWIthBgpVpn(routerName, NatConstants.INVALID_ID, true);
+
+ // Get the group ID
+ long groupId = createGroupId(getGroupIdKey(routerName));
+ installFlowsWithUpdatedVpnId(primarySwitchId, routerName, groupId, NatConstants.INVALID_ID, routerId);
+ }
+ }
+
+ boolean chkExtRtrAndSnatEnbl(Uuid routerUuid){
+ InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class).child
+ (Routers.class, new RoutersKey(routerUuid.getValue())).build();
+ Optional<Routers> routerData = read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerInstanceIndentifier);
+ if (routerData.isPresent() && routerData.get().isEnableSnat()) {
+ return true;
+ }
+ return false;
+ }
+
+ public void installFlowsWithUpdatedVpnId(BigInteger primarySwitchId, String routerName, long groupId, long bgpVpnId, long routerId){
+ long changedVpnId = bgpVpnId;
+ String logMsg = "NAT Service : Update the BGP VPN ID {}";
+ if (bgpVpnId == NatConstants.INVALID_ID){
+ changedVpnId = routerId;
+ logMsg = "NAT Service : Update the router ID {}";
+ }
+
+ LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the primary switch {}",
+ changedVpnId, groupId, primarySwitchId);
+ FlowEntity flowEntity = buildSnatFlowEntityWithUpdatedVpnId(primarySwitchId, routerName, groupId, changedVpnId);
+ mdsalManager.installFlow(flowEntity);
+
+ LOG.debug(logMsg + " in the Terminating Service table (table ID 36) which forwards the packet" +
+ " to the table 46 in the Primary switch {}", changedVpnId, primarySwitchId);
+ installTerminatingServiceTblEntryWithUpdatedVpnId(primarySwitchId, routerName, changedVpnId);
+
+ LOG.debug(logMsg + " in the Outbound NAPT table (table ID 46) which punts the packet to the" +
+ " controller in the Primary switch {}", changedVpnId, primarySwitchId);
+ createOutboundTblEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
+
+ LOG.debug(logMsg + " in the NAPT PFIB TABLE which forwards the outgoing packet to FIB Table in the Primary switch {}",
+ changedVpnId, primarySwitchId);
+ installNaptPfibEntryWithBgpVpn(primarySwitchId, routerId, changedVpnId);
+
+ LOG.debug(logMsg + " in the NAPT flows for the Outbound NAPT table (table ID 46) and the INBOUND NAPT table (table ID 44)" +
+ " in the Primary switch {}", changedVpnId, primarySwitchId);
+ updateNaptFlowsWithVpnId(primarySwitchId, routerId, bgpVpnId);
+
+ List<BigInteger> switches = NatUtil.getDpnsForRouter(dataBroker, routerName);
+ for(BigInteger dpnId : switches) {
+ // Update the BGP VPN ID in the SNAT miss entry to group
+ if( !dpnId.equals(primarySwitchId) ) {
+ LOG.debug(logMsg + " in the SNAT miss entry pointing to group {} in the non NAPT switch {}",
+ changedVpnId, groupId, dpnId);
+ flowEntity = buildSnatFlowEntityWithUpdatedVpnId(dpnId, routerName, groupId, changedVpnId);
+ mdsalManager.installFlow(flowEntity);
+ }
+ }
+ }
+
+ public void updateNaptFlowsWithVpnId(BigInteger dpnId, long routerId, long bgpVpnId){
+ //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
+ IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
+ if(ipPortMapping == null){
+ LOG.error("NAT Service : Unable to retrieve the IpPortMapping");
+ return;
+ }
+
+ List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
+ for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes){
+ List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
+ for(IpPortMap ipPortMap : ipPortMaps){
+ String ipPortInternal = ipPortMap.getIpPortInternal();
+ String[] ipPortParts = ipPortInternal.split(":");
+ if(ipPortParts.length != 2) {
+ LOG.error("NAT Service : Unable to retrieve the Internal IP and port");
+ return;
+ }
+ String internalIp = ipPortParts[0];
+ String internalPort = ipPortParts[1];
+
+ ProtocolTypes protocolTypes = intextIpProtocolType.getProtocol();
+ NAPTEntryEvent.Protocol protocol;
+ switch (protocolTypes){
+ case TCP:
+ protocol = NAPTEntryEvent.Protocol.TCP;
+ break;
+ case UDP:
+ protocol = NAPTEntryEvent.Protocol.UDP;
+ break;
+ default:
+ protocol = NAPTEntryEvent.Protocol.TCP;
+ }
+ SessionAddress internalAddress = new SessionAddress(internalIp, Integer.valueOf(internalPort));
+ SessionAddress externalAddress = naptManager.getExternalAddressMapping(routerId, internalAddress, protocol);
+ long internetVpnid = NatUtil.getVpnId(dataBroker, routerId);
+ naptEventHandler.buildAndInstallNatFlows(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, internetVpnid, routerId, bgpVpnId,
+ internalAddress, externalAddress, protocol);
+ naptEventHandler.buildAndInstallNatFlows(dpnId, NatConstants.INBOUND_NAPT_TABLE, internetVpnid, routerId, bgpVpnId,
+ externalAddress, internalAddress, protocol);
+
+ }
+ }
+ }
+
+ public FlowEntity buildSnatFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long groupId, long changedVpnId) {
+
+ LOG.debug("NAT Service : buildSnatFlowEntity is called for dpId {}, routerName {} groupId {} changed VPN ID {}", dpId, routerName, groupId, changedVpnId );
+ List<MatchInfo> matches = new ArrayList<>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
+
+ List<InstructionInfo> instructions = new ArrayList<>();
+ List<ActionInfo> actionsInfo = new ArrayList<>();
+
+ ActionInfo actionSetField = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
+ BigInteger.valueOf(changedVpnId)}) ;
+ actionsInfo.add(actionSetField);
+ LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
+ actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
+ instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfo));
+ String flowRef = getFlowRefSnat(dpId, NatConstants.PSNAT_TABLE, routerName);
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
+ NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_SNAT_TABLE, matches, instructions);
+
+ LOG.debug("NAT Service : Returning SNAT Flow Entity {}", flowEntity);
+ return flowEntity;
+ }
+
+ // TODO : Replace this with ITM Rpc once its available with full functionality
+ protected void installTerminatingServiceTblEntryWithUpdatedVpnId(BigInteger dpnId, String routerName, long changedVpnId) {
+ LOG.debug("NAT Service : installTerminatingServiceTblEntryWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpnId, routerName, changedVpnId);
+ FlowEntity flowEntity = buildTsFlowEntityWithUpdatedVpnId(dpnId, routerName, changedVpnId);
+ mdsalManager.installFlow(flowEntity);
+
+ }
+
+ private FlowEntity buildTsFlowEntityWithUpdatedVpnId(BigInteger dpId, String routerName, long changedVpnId) {
+ LOG.debug("NAT Service : buildTsFlowEntityWithUpdatedVpnId called for switch {}, routerName {}, BGP VPN ID {}", dpId, routerName, changedVpnId);
+ BigInteger routerId = BigInteger.valueOf (NatUtil.getVpnId(dataBroker, routerName));
+ BigInteger bgpVpnIdAsBigInt = BigInteger.valueOf(changedVpnId);
+ List<MatchInfo> matches = new ArrayList<>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+ matches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {bgpVpnIdAsBigInt }));
+
+ List<InstructionInfo> instructions = new ArrayList<>();
+ instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]
+ { bgpVpnIdAsBigInt, MetaDataUtil.METADATA_MASK_VRFID }));
+ instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]
+ { NatConstants.OUTBOUND_NAPT_TABLE }));
+ String flowRef = getFlowRefTs(dpId, NatConstants.TERMINATING_SERVICE_TABLE, routerId.longValue());
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.TERMINATING_SERVICE_TABLE, flowRef,
+ NatConstants.DEFAULT_TS_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_TS_TABLE, matches, instructions);
+ return flowEntity;
+ }
+
+ public void createOutboundTblEntryWithBgpVpn(BigInteger dpnId, long routerId, long changedVpnId) {
+ LOG.debug("NAT Service : createOutboundTblEntry called for dpId {} and routerId {}, BGP VPN ID {}", dpnId, routerId, changedVpnId);
+ FlowEntity flowEntity = buildOutboundFlowEntityWithBgpVpn(dpnId, routerId, changedVpnId);
+ LOG.debug("NAT Service : Installing flow {}", flowEntity);
+ mdsalManager.installFlow(flowEntity);
+ }
+
+ protected FlowEntity buildOutboundFlowEntityWithBgpVpn(BigInteger dpId, long routerId, long changedVpnId) {
+ LOG.debug("NAT Service : buildOutboundFlowEntityWithBgpVpn called for dpId {} and routerId {}, BGP VPN ID {}", dpId, routerId, changedVpnId);
+ List<MatchInfo> matches = new ArrayList<>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[]{0x0800L}));
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[]{
+ BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID}));
+
+ List<InstructionInfo> instructions = new ArrayList<>();
+ List<ActionInfo> actionsInfos = new ArrayList<>();
+ actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
+ instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+ instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]{BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID}));
+
+ String flowRef = getFlowRefOutbound(dpId, NatConstants.OUTBOUND_NAPT_TABLE, routerId);
+ BigInteger cookie = getCookieOutboundFlow(routerId);
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.OUTBOUND_NAPT_TABLE, flowRef,
+ 5, flowRef, 0, 0,
+ cookie, matches, instructions);
+ LOG.debug("NAT Service : returning flowEntity {}", flowEntity);
+ return flowEntity;
+ }
+
+ public void installNaptPfibEntryWithBgpVpn(BigInteger dpnId, long segmentId, long changedVpnId) {
+ LOG.debug("NAT Service : installNaptPfibEntryWithBgpVpn called for dpnId {} and segmentId {} ,BGP VPN ID {}", dpnId, segmentId, changedVpnId);
+ FlowEntity naptPfibFlowEntity = buildNaptPfibFlowEntityWithUpdatedVpnId(dpnId, segmentId, changedVpnId);
+ mdsalManager.installFlow(naptPfibFlowEntity);
+ }
+
+ public FlowEntity buildNaptPfibFlowEntityWithUpdatedVpnId(BigInteger dpId, long segmentId, long changedVpnId) {
+
+ LOG.debug("NAT Service : buildNaptPfibFlowEntityWithUpdatedVpnId is called for dpId {}, segmentId {}, BGP VPN ID {}", dpId, segmentId, changedVpnId);
+ List<MatchInfo> matches = new ArrayList<>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ BigInteger.valueOf(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
+
+ ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
+ ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
+ listActionInfo.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NatConstants.L3_FIB_TABLE) }));
+ instructionInfo.add(new InstructionInfo(InstructionType.apply_actions, listActionInfo));
+
+ String flowRef = getFlowRefTs(dpId, NatConstants.NAPT_PFIB_TABLE, segmentId);
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.NAPT_PFIB_TABLE, flowRef,
+ NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_SNAT_TABLE, matches, instructionInfo);
+
+ LOG.debug("NAT Service : Returning NaptPFib Flow Entity {}", flowEntity);
+ return flowEntity;
+ }
+
+ @Override
+ protected ExternalRoutersListener getDataTreeChangeListener()
+ {
+ return ExternalRoutersListener.this;
+ }
+
+}
--- /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.natservice.internal;
+
+import java.math.BigInteger;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+
+public interface FloatingIPHandler {
+
+ void onAddFloatingIp(BigInteger dpnId, String routerId, Uuid networkId, String interfaceName, String externalIp,
+ String internalIp);
+
+ void onRemoveFloatingIp(BigInteger dpnId, String routerId, Uuid networkId, String externalIp, String internalIp,
+ long label);
+
+}
--- /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.natservice.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.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.ActionType;
+import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
+import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
+import org.opendaylight.vpnservice.mdsalutil.InstructionType;
+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.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ext.routers.Routers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.FloatingIpInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.RouterPorts;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.Ports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.PortsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.PortsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.ports.IpMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.ports.IpMappingBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.ports.IpMappingKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.networks.Networks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.networks.NetworksKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ExternalNetworks;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+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.OdlInterfaceRpcService;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Strings;
+
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by emhamla on 1/18/2016.
+ */
+public class FloatingIPListener extends org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener<IpMapping> implements AutoCloseable{
+ private static final Logger LOG = LoggerFactory.getLogger(FloatingIPListener.class);
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private OdlInterfaceRpcService interfaceManager;
+ private IMdsalApiManager mdsalManager;
+ private FloatingIPHandler handler;
+
+
+ public FloatingIPListener (final DataBroker db) {
+ super(IpMapping.class);
+ broker = db;
+ registerListener(db);
+ }
+
+ void setFloatingIpHandler(FloatingIPHandler handler) {
+ this.handler = handler;
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("FloatingIP Listener Closed");
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ getWildCardPath(), FloatingIPListener.this, AsyncDataBroker.DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("FloatingIP DataChange listener registration fail!", e);
+ throw new IllegalStateException("FloatingIP Listener registration Listener failed.", e);
+ }
+ }
+
+ private InstanceIdentifier<IpMapping> getWildCardPath() {
+ return InstanceIdentifier.create(FloatingIpInfo.class).child(RouterPorts.class).child(Ports.class).child(IpMapping.class);
+ }
+
+ public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
+ this.interfaceManager = interfaceManager;
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ @Override
+ protected void add(final InstanceIdentifier<IpMapping> identifier,
+ final IpMapping mapping) {
+ LOG.trace("FloatingIPListener add ip mapping method - key: " + identifier + ", value=" + mapping );
+ processFloatingIPAdd(identifier, mapping);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<IpMapping> identifier, IpMapping mapping) {
+ LOG.trace("FloatingIPListener remove ip mapping method - key: " + identifier + ", value=" + mapping );
+ processFloatingIPDel(identifier, mapping);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<IpMapping> identifier, IpMapping original, IpMapping update) {
+ LOG.trace("FloatingIPListener update ip mapping method - key: " + identifier + ", original=" + original + ", update=" + update );
+ }
+
+ public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
+ BigInteger nodeId = BigInteger.ZERO;
+ try {
+ GetDpidFromInterfaceInput
+ dpIdInput =
+ new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
+ Future<RpcResult<GetDpidFromInterfaceOutput>>
+ dpIdOutput =
+ interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
+ RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
+ if (dpIdResult.isSuccessful()) {
+ nodeId = dpIdResult.getResult().getDpid();
+ } else {
+ LOG.error("Could not retrieve DPN Id for interface {}", ifName);
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Exception when getting dpn for interface {}", ifName, e);
+ }
+ return nodeId;
+ }
+
+ private FlowEntity buildPreDNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId, long vpnId) {
+ return buildPreDNATFlowEntity(dpId, internalIp, externalIp, routerId, vpnId, NatConstants.INVALID_ID);
+ }
+
+ private FlowEntity buildPreDNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId, long vpnId, long associatedVpn) {
+ LOG.info("Bulding DNAT Flow entity for ip {} ", externalIp);
+
+ long segmentId = (associatedVpn == NatConstants.INVALID_ID) ? routerId : associatedVpn;
+ LOG.debug("Segment id {} in build preDNAT Flow", segmentId);
+
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+
+ matches.add(new MatchInfo(MatchFieldType.ipv4_destination, new String[] {
+ externalIp, "32" }));
+
+// matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+// BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
+
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+ actionsInfos.add(new ActionInfo(ActionType.set_destination_ip, new String[]{ internalIp, "32" }));
+
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf
+ (segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
+ instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+ instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.DNAT_TABLE }));
+
+ String flowRef = NatUtil.getFlowRef(dpId, NatConstants.PDNAT_TABLE, routerId, externalIp);
+
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PDNAT_TABLE, flowRef,
+ NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_DNAT_TABLE, matches, instructions);
+
+ return flowEntity;
+ }
+
+
+
+ private FlowEntity buildDNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId) {
+ return buildDNATFlowEntity(dpId, internalIp, externalIp, routerId, NatConstants.INVALID_ID);
+ }
+
+ private FlowEntity buildDNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId, long associatedVpn) {
+
+ LOG.info("Bulding DNAT Flow entity for ip {} ", externalIp);
+
+ long segmentId = (associatedVpn == NatConstants.INVALID_ID) ? routerId : associatedVpn;
+ LOG.debug("Segment id {} in build DNAT", segmentId);
+
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ BigInteger.valueOf(segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
+
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+
+ matches.add(new MatchInfo(MatchFieldType.ipv4_destination, new String[] {
+ // externalIp, "32" }));
+ internalIp, "32" }));
+
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+// actionsInfos.add(new ActionInfo(ActionType.set_destination_ip, new String[]{ internalIp, "32" }));
+
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+// instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf
+// (routerId), MetaDataUtil.METADATA_MASK_VRFID }));
+ actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NatConstants.L3_FIB_TABLE) }));
+ instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+ //instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.L3_FIB_TABLE }));
+
+ String flowRef = NatUtil.getFlowRef(dpId, NatConstants.DNAT_TABLE, routerId, externalIp);
+
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.DNAT_TABLE, flowRef,
+ NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_DNAT_TABLE, matches, instructions);
+
+ return flowEntity;
+
+ }
+
+ private FlowEntity buildPreSNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long vpnId, long routerId) {
+ return buildPreSNATFlowEntity(dpId, internalIp, externalIp, vpnId, routerId, NatConstants.INVALID_ID);
+ }
+
+ private FlowEntity buildPreSNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long vpnId, long routerId, long associatedVpn) {
+
+ LOG.info("Building PSNAT Flow entity for ip {} ", internalIp);
+
+ long segmentId = (associatedVpn == NatConstants.INVALID_ID) ? routerId : associatedVpn;
+
+ LOG.debug("Segment id {} in build preSNAT flow", segmentId);
+
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+
+ matches.add(new MatchInfo(MatchFieldType.ipv4_source, new String[] {
+ internalIp, "32" }));
+
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ BigInteger.valueOf(segmentId), MetaDataUtil.METADATA_MASK_VRFID }));
+
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+ actionsInfos.add(new ActionInfo(ActionType.set_source_ip, new String[]{ externalIp, "32" }));
+
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
+ instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+ instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.SNAT_TABLE }));
+
+ String flowRef = NatUtil.getFlowRef(dpId, NatConstants.PSNAT_TABLE, routerId, internalIp);
+
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
+ NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_DNAT_TABLE, matches, instructions);
+
+ return flowEntity;
+ }
+
+ private FlowEntity buildSNATFlowEntity(BigInteger dpId, String internalIp, String externalIp, long vpnId, String macAddress) {
+
+ LOG.info("Building SNAT Flow entity for ip {} ", internalIp);
+
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
+
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+
+ matches.add(new MatchInfo(MatchFieldType.ipv4_source, new String[] {
+ // internalIp, "32" }));
+ externalIp, "32" }));
+
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+// actionsInfos.add(new ActionInfo(ActionType.set_source_ip, new String[]{ externalIp, "32" }));
+
+ //TODO: Set external gateway mac address
+ if(!Strings.isNullOrEmpty(macAddress)) {
+ LOG.debug("Setting ext gw mac address {} in SNAT {} flow action", macAddress, internalIp);
+ actionsInfos.add(new ActionInfo(ActionType.set_field_eth_dest, new String[]{ macAddress }));
+ }
+
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ //instructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] { BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
+ actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NatConstants.L3_FIB_TABLE) }));
+ instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+ //instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.L3_FIB_TABLE }));
+
+ String flowRef = NatUtil.getFlowRef(dpId, NatConstants.SNAT_TABLE, vpnId, internalIp);
+
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.SNAT_TABLE, flowRef,
+ NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_DNAT_TABLE, matches, instructions);
+
+ return flowEntity;
+
+
+ }
+
+ private void createDNATTblEntry(BigInteger dpnId, String internalIp, String externalIp, long routerId, long vpnId, long associatedVpnId) {
+ FlowEntity pFlowEntity = buildPreDNATFlowEntity(dpnId, internalIp, externalIp, routerId, vpnId, associatedVpnId );
+ mdsalManager.installFlow(pFlowEntity);
+
+ FlowEntity flowEntity = buildDNATFlowEntity(dpnId, internalIp, externalIp, routerId, associatedVpnId);
+ mdsalManager.installFlow(flowEntity);
+ }
+
+ private void removeDNATTblEntry(BigInteger dpnId, String internalIp, String externalIp, long routerId) {
+ FlowEntity pFlowEntity = buildPreDNATDeleteFlowEntity(dpnId, internalIp, externalIp, routerId );
+ mdsalManager.removeFlow(pFlowEntity);
+
+ FlowEntity flowEntity = buildDNATDeleteFlowEntity(dpnId, internalIp, externalIp, routerId);
+ mdsalManager.removeFlow(flowEntity);
+ }
+
+ private void createSNATTblEntry(BigInteger dpnId, String internalIp, String externalIp, long vpnId, long routerId, String macAddress, long associatedVpnId) {
+ FlowEntity pFlowEntity = buildPreSNATFlowEntity(dpnId, internalIp, externalIp, vpnId , routerId, associatedVpnId);
+ mdsalManager.installFlow(pFlowEntity);
+
+ FlowEntity flowEntity = buildSNATFlowEntity(dpnId, internalIp, externalIp, vpnId, macAddress);
+ mdsalManager.installFlow(flowEntity);
+
+ }
+
+ private void removeSNATTblEntry(BigInteger dpnId, String internalIp, long routerId, String externalIp, long vpnId) {
+ FlowEntity pFlowEntity = buildPreSNATDeleteFlowEntity(dpnId, internalIp, routerId, externalIp);
+ mdsalManager.removeFlow(pFlowEntity);
+
+ FlowEntity flowEntity = buildSNATDeleteFlowEntity(dpnId, internalIp, vpnId, externalIp);
+ mdsalManager.removeFlow(flowEntity);
+
+ }
+
+ private Uuid getExtNetworkId(final InstanceIdentifier<RouterPorts> pIdentifier) {
+ Optional<RouterPorts> rtrPort = NatUtil.read(broker, LogicalDatastoreType.CONFIGURATION, pIdentifier);
+ if(!rtrPort.isPresent()) {
+ LOG.error("Unable to read router port entry for {}", pIdentifier);
+ return null;
+ }
+
+ Uuid extNwId = rtrPort.get().getExternalNetworkId();
+ return extNwId;
+ }
+
+ private long getVpnId(Uuid extNwId) {
+ InstanceIdentifier<Networks> nwId = InstanceIdentifier.builder(ExternalNetworks.class).child(Networks.class, new NetworksKey(extNwId)).build();
+ Optional<Networks> nw = NatUtil.read(broker, LogicalDatastoreType.CONFIGURATION, nwId);
+ if(!nw.isPresent()) {
+ LOG.error("Unable to read external network for {}", extNwId);
+ return NatConstants.INVALID_ID;
+ }
+
+ Uuid vpnUuid = nw.get().getVpnid();
+ if(vpnUuid == null) {
+ return NatConstants.INVALID_ID;
+ }
+
+ //Get the id using the VPN UUID (also vpn instance name)
+ return NatUtil.readVpnId(broker, vpnUuid.getValue());
+ }
+
+ private void processFloatingIPAdd(final InstanceIdentifier<IpMapping> identifier,
+ final IpMapping mapping) {
+ LOG.trace("Add event - key: {}, value: {}", identifier, mapping);
+
+ final String routerId = identifier.firstKeyOf(RouterPorts.class).getRouterId();
+ final PortsKey pKey = identifier.firstKeyOf(Ports.class);
+ String interfaceName = pKey.getPortName();
+
+ InstanceIdentifier<RouterPorts> pIdentifier = identifier.firstIdentifierOf(RouterPorts.class);
+ createNATFlowEntries(interfaceName, mapping, pIdentifier, routerId);
+ }
+
+ private void processFloatingIPDel(final InstanceIdentifier<IpMapping> identifier,
+ final IpMapping mapping) {
+ LOG.trace("Del event - key: {}, value: {}", identifier, mapping);
+
+ final String routerId = identifier.firstKeyOf(RouterPorts.class).getRouterId();
+ final PortsKey pKey = identifier.firstKeyOf(Ports.class);
+ String interfaceName = pKey.getPortName();
+
+ InstanceIdentifier<RouterPorts> pIdentifier = identifier.firstIdentifierOf(RouterPorts.class);
+ removeNATFlowEntries(interfaceName, mapping, pIdentifier, routerId);
+ }
+
+ private InetAddress getInetAddress(String ipAddr) {
+ InetAddress ipAddress = null;
+ try {
+ ipAddress = InetAddress.getByName(ipAddr);
+ } catch (UnknownHostException e) {
+ LOG.error("UnknowHostException for ip {}", ipAddr);
+ }
+ return ipAddress;
+ }
+
+ private boolean validateIpMapping(IpMapping mapping) {
+ return getInetAddress(mapping.getInternalIp()) != null &&
+ getInetAddress(mapping.getExternalIp()) != null;
+ }
+
+ void createNATFlowEntries(String interfaceName, final IpMapping mapping,
+ final InstanceIdentifier<RouterPorts> pIdentifier, final String routerName) {
+ if(!validateIpMapping(mapping)) {
+ LOG.warn("Not a valid ip addresses in the mapping {}", mapping);
+ return;
+ }
+
+ //Get the DPN on which this interface resides
+ BigInteger dpnId = getDpnForInterface(interfaceManager, interfaceName);
+
+ if(dpnId.equals(BigInteger.ZERO)) {
+ LOG.error("No DPN for interface {}. NAT flow entries for ip mapping {} will not be installed",
+ interfaceName, mapping);
+ return;
+ }
+
+ long routerId = NatUtil.getVpnId(broker, routerName);
+ if(routerId == NatConstants.INVALID_ID) {
+ LOG.warn("Could not retrieve router id for {} to create NAT Flow entries", routerName);
+ return;
+ }
+ //Check if the router to vpn association is present
+ //long associatedVpnId = NatUtil.getAssociatedVpn(broker, routerName);
+ Uuid associatedVpn = NatUtil.getVpnForRouter(broker, routerName);
+ long associatedVpnId = NatConstants.INVALID_ID;
+ if(associatedVpn == null) {
+ LOG.debug("Router {} is not assicated with any BGP VPN instance", routerName);
+ } else {
+ LOG.debug("Router {} is associated with VPN Instance with Id {}", routerName, associatedVpn);
+ associatedVpnId = NatUtil.getVpnId(broker, associatedVpn.getValue());
+ LOG.debug("vpninstance Id is {} for VPN {}", associatedVpnId, associatedVpn);
+ //routerId = associatedVpnId;
+ }
+
+ Uuid extNwId = getExtNetworkId(pIdentifier);
+ if(extNwId == null) {
+ LOG.error("External network associated with interface {} could not be retrieved", interfaceName);
+ LOG.error("NAT flow entries will not be installed {}", mapping);
+ return;
+ }
+ long vpnId = getVpnId(extNwId);
+ if(vpnId < 0) {
+ LOG.error("No VPN associated with Ext nw {}. Unable to create SNAT table entry for fixed ip {}",
+ extNwId, mapping.getInternalIp());
+ return;
+ }
+
+ //Create the DNAT and SNAT table entries
+ createDNATTblEntry(dpnId, mapping.getInternalIp(), mapping.getExternalIp(), routerId, vpnId, associatedVpnId);
+
+
+ String macAddr = getExternalGatewayMacAddress(routerName);
+ createSNATTblEntry(dpnId, mapping.getInternalIp(), mapping.getExternalIp(), vpnId, routerId, macAddr, associatedVpnId);
+
+ handler.onAddFloatingIp(dpnId, routerName, extNwId, interfaceName, mapping.getExternalIp(), mapping
+ .getInternalIp());
+ }
+
+ void createNATFlowEntries(BigInteger dpnId, String interfaceName, String routerName, Uuid externalNetworkId, String internalIp, String externalIp) {
+ long routerId = NatUtil.getVpnId(broker, routerName);
+ if(routerId == NatConstants.INVALID_ID) {
+ LOG.warn("Could not retrieve router id for {} to create NAT Flow entries", routerName);
+ return;
+ }
+ //Check if the router to vpn association is present
+ long associatedVpnId = NatUtil.getAssociatedVpn(broker, routerName);
+ if(associatedVpnId == NatConstants.INVALID_ID) {
+ LOG.debug("Router {} is not assicated with any BGP VPN instance", routerName);
+ } else {
+ LOG.debug("Router {} is associated with VPN Instance with Id {}", routerName, associatedVpnId);
+ //routerId = associatedVpnId;
+ }
+
+ long vpnId = getVpnId(externalNetworkId);
+ if(vpnId < 0) {
+ LOG.error("Unable to create SNAT table entry for fixed ip {}", internalIp);
+ return;
+ }
+ //Create the DNAT and SNAT table entries
+ createDNATTblEntry(dpnId, internalIp, externalIp, routerId, vpnId, associatedVpnId);
+
+ String macAddr = getExternalGatewayMacAddress(routerName);
+ createSNATTblEntry(dpnId, internalIp, externalIp, vpnId, routerId, macAddr, associatedVpnId);
+
+ handler.onAddFloatingIp(dpnId, routerName, externalNetworkId, interfaceName, externalIp, internalIp);
+ }
+
+ void createNATOnlyFlowEntries(BigInteger dpnId, String interfaceName, String routerName, String associatedVPN, Uuid externalNetworkId, String internalIp, String externalIp) {
+ //String segmentId = associatedVPN == null ? routerName : associatedVPN;
+ LOG.debug("Retrieving vpn id for VPN {} to proceed with create NAT Flows", routerName);
+ long routerId = NatUtil.getVpnId(broker, routerName);
+ if(routerId == NatConstants.INVALID_ID) {
+ LOG.warn("Could not retrieve vpn id for {} to create NAT Flow entries", routerName);
+ return;
+ }
+ long associatedVpnId = NatUtil.getVpnId(broker, associatedVPN);
+ LOG.debug("Associated VPN Id {} for router {}", associatedVpnId, routerName);
+ long vpnId = getVpnId(externalNetworkId);
+ if(vpnId < 0) {
+ LOG.error("Unable to create SNAT table entry for fixed ip {}", internalIp);
+ return;
+ }
+ //Create the DNAT and SNAT table entries
+ //createDNATTblEntry(dpnId, internalIp, externalIp, routerId, vpnId);
+ FlowEntity pFlowEntity = buildPreDNATFlowEntity(dpnId, internalIp, externalIp, routerId, vpnId, associatedVpnId );
+ mdsalManager.installFlow(pFlowEntity);
+
+ FlowEntity flowEntity = buildDNATFlowEntity(dpnId, internalIp, externalIp, routerId, associatedVpnId);
+ mdsalManager.installFlow(flowEntity);
+
+ String macAddr = getExternalGatewayMacAddress(routerName);
+ //createSNATTblEntry(dpnId, internalIp, externalIp, vpnId, routerId, macAddr);
+ pFlowEntity = buildPreSNATFlowEntity(dpnId, internalIp, externalIp, vpnId , routerId, associatedVpnId);
+ mdsalManager.installFlow(pFlowEntity);
+
+ flowEntity = buildSNATFlowEntity(dpnId, internalIp, externalIp, vpnId, macAddr);
+ mdsalManager.installFlow(flowEntity);
+
+ }
+
+ private String getExternalGatewayMacAddress(String routerName) {
+ InstanceIdentifier<Routers> routersIdentifier = NatUtil.buildRouterIdentifier(routerName);
+ Optional<Routers> optRouters = NatUtil.read(broker, LogicalDatastoreType.CONFIGURATION, routersIdentifier);
+ if(optRouters.isPresent()) {
+ Routers routers = optRouters.get();
+ return routers.getExtGwMacAddress();
+ }
+ return "";
+ }
+
+ void removeNATFlowEntries(String interfaceName, final IpMapping mapping,
+ final InstanceIdentifier<RouterPorts> pIdentifier, final String routerName) {
+
+ //Get the DPN on which this interface resides
+ BigInteger dpnId = getDpnForInterface(interfaceManager, interfaceName);
+ if(dpnId.equals(BigInteger.ZERO)) {
+ LOG.info("Abort processing Floating ip configuration. No DPN for port : {}", interfaceName);
+ return;
+ }
+
+ long routerId = NatUtil.getVpnId(broker, routerName);
+ if(routerId == NatConstants.INVALID_ID) {
+ LOG.warn("Could not retrieve router id for {} to remove NAT Flow entries", routerName);
+ return;
+ }
+ //if(routerId == NatConstants.INVALID_ID) {
+ //The router could be associated with BGP VPN
+ Uuid associatedVPN = NatUtil.getVpnForRouter(broker, routerName);
+ long associatedVpnId = NatConstants.INVALID_ID;
+ if(associatedVPN == null) {
+ LOG.warn("Could not retrieve router id for {} to remove NAT Flow entries", routerName);
+ } else {
+ LOG.debug("Retrieving vpn id for VPN {} to proceed with remove NAT Flows", associatedVPN.getValue());
+ associatedVpnId = NatUtil.getVpnId(broker, associatedVPN.getValue());
+ }
+
+ //Delete the DNAT and SNAT table entries
+ removeDNATTblEntry(dpnId, mapping.getInternalIp(), mapping.getExternalIp(), routerId);
+
+ Uuid extNwId = getExtNetworkId(pIdentifier);
+ if(extNwId == null) {
+ LOG.error("External network associated with interface {} could not be retrieved", interfaceName);
+ return;
+ }
+ long vpnId = getVpnId(extNwId);
+ if(vpnId < 0) {
+ LOG.error("No VPN associated with ext nw {}. Unable to delete SNAT table entry for fixed ip {}",
+ extNwId, mapping.getInternalIp());
+ return;
+ }
+ removeSNATTblEntry(dpnId, mapping.getInternalIp(), routerId, mapping.getExternalIp(), vpnId);
+
+ long label = getOperationalIpMapping(routerName, interfaceName, mapping.getInternalIp());
+ if(label < 0) {
+ LOG.error("Could not retrieve label for prefix {} in router {}", mapping.getInternalIp(), routerId);
+ return;
+ }
+ //Uuid extNwId = getExtNetworkId(pIdentifier);
+// Uuid extNwId = getExternalNetworkForRouter(routerName);
+// if(extNwId == null) {
+// LOG.error("External network associated with router {} could not be retrieved", routerName);
+// return;
+// }
+ handler.onRemoveFloatingIp(dpnId, routerName, extNwId, mapping.getExternalIp(), mapping.getInternalIp(), (int) label);
+ removeOperationalDS(routerName, interfaceName, mapping.getInternalIp(), mapping.getExternalIp());
+
+ }
+
+ void removeNATFlowEntries(BigInteger dpnId, String interfaceName, String vpnName, String routerName, Uuid externalNetworkId, String internalIp, String externalIp) {
+ long routerId = NatUtil.getVpnId(broker, routerName);
+ if(routerId == NatConstants.INVALID_ID) {
+ LOG.warn("Could not retrieve router id for {} to remove NAT Flow entries", routerName);
+ return;
+ }
+
+ long vpnId = NatUtil.getVpnId(broker, vpnName);
+ if(vpnId == NatConstants.INVALID_ID) {
+ LOG.warn("VPN Id not found for {} to remove NAT flow entries {}", vpnName, internalIp);
+ }
+
+ //Delete the DNAT and SNAT table entries
+ removeDNATTblEntry(dpnId, internalIp, externalIp, routerId);
+
+ removeSNATTblEntry(dpnId, internalIp, routerId, externalIp, vpnId);
+
+ long label = getOperationalIpMapping(routerName, interfaceName, internalIp);
+ if(label < 0) {
+ LOG.error("Could not retrieve label for prefix {} in router {}", internalIp, routerId);
+ return;
+ }
+ //handler.onRemoveFloatingIp(dpnId, routerName, externalNetworkId, externalIp, internalIp, (int)label);
+ ((VpnFloatingIpHandler)handler).cleanupFibEntries(dpnId, vpnName, externalIp, label);
+ removeOperationalDS(routerName, interfaceName, internalIp, externalIp);
+ }
+
+ void removeNATOnlyFlowEntries(BigInteger dpnId, String interfaceName, String routerName, String associatedVPN,
+ String internalIp, String externalIp) {
+ String segmentId = associatedVPN == null ? routerName : associatedVPN;
+ LOG.debug("Retrieving vpn id for VPN {} to proceed with remove NAT Flows", segmentId);
+ long routerId = NatUtil.getVpnId(broker, segmentId);
+ if(routerId == NatConstants.INVALID_ID) {
+ LOG.warn("Could not retrieve vpn id for {} to remove NAT Flow entries", segmentId);
+ return;
+ }
+ //Delete the DNAT and SNAT table entries
+ removeDNATTblEntry(dpnId, internalIp, externalIp, routerId);
+
+ //removeSNATTblEntry(dpnId, internalIp, routerId, externalIp);
+ }
+
+ private long getOperationalIpMapping(String routerId, String interfaceName, String internalIp) {
+ InstanceIdentifier<IpMapping> ipMappingIdentifier = NatUtil.getIpMappingIdentifier(routerId, interfaceName, internalIp);
+ Optional<IpMapping> ipMapping = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, ipMappingIdentifier);
+ if(ipMapping.isPresent()) {
+ return ipMapping.get().getLabel();
+ }
+ return NatConstants.INVALID_ID;
+ }
+
+ private Uuid getExternalNetworkForRouter(String routerId) {
+ InstanceIdentifier<RouterPorts> identifier = NatUtil.getRouterPortsId(routerId);
+ Optional<RouterPorts> optRouterPorts = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
+ if(optRouterPorts.isPresent()) {
+ RouterPorts routerPorts = optRouterPorts.get();
+ return routerPorts.getExternalNetworkId();
+ }
+ return null;
+ }
+
+ void updateOperationalDS(String routerId, String interfaceName, int label, String internalIp, String externalIp) {
+
+ LOG.info("Updating operational DS for floating ip config : {} with label {}", internalIp, label);
+ InstanceIdentifier<Ports> portsId = NatUtil.getPortsIdentifier(routerId, interfaceName);
+ Optional<Ports> optPorts = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, portsId);
+ IpMapping ipMapping = new IpMappingBuilder().setKey(new IpMappingKey(internalIp)).setInternalIp(internalIp)
+ .setExternalIp(externalIp).setLabel(label).build();
+ if(optPorts.isPresent()) {
+ LOG.debug("Ports {} entry already present. Updating ipmapping for internal ip {}", interfaceName, internalIp);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, portsId.child(IpMapping.class, new IpMappingKey(internalIp)), ipMapping);
+ } else {
+ LOG.debug("Adding Ports entry {} along with ipmapping {}", interfaceName, internalIp);
+ List<IpMapping> ipMappings = new ArrayList<>();
+ ipMappings.add(ipMapping);
+ Ports ports = new PortsBuilder().setKey(new PortsKey(interfaceName)).setPortName(interfaceName).setIpMapping(ipMappings).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, portsId, ports);
+ }
+ }
+
+ void removeOperationalDS(String routerId, String interfaceName, String internalIp, String externalIp) {
+ LOG.info("Remove operational DS for floating ip config: {}", internalIp);
+ InstanceIdentifier<IpMapping> ipMappingId = NatUtil.getIpMappingIdentifier(routerId, interfaceName, internalIp);
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, ipMappingId);
+ }
+
+ private FlowEntity buildPreDNATDeleteFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId) {
+
+ LOG.info("Bulding Delete DNAT Flow entity for ip {} ", externalIp);
+
+ String flowRef = NatUtil.getFlowRef(dpId, NatConstants.PDNAT_TABLE, routerId, externalIp);
+
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PDNAT_TABLE, flowRef,
+ NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_DNAT_TABLE, null, null);
+
+ return flowEntity;
+ }
+
+
+
+ private FlowEntity buildDNATDeleteFlowEntity(BigInteger dpId, String internalIp, String externalIp, long routerId) {
+
+ LOG.info("Bulding Delete DNAT Flow entity for ip {} ", externalIp);
+
+ String flowRef = NatUtil.getFlowRef(dpId, NatConstants.DNAT_TABLE, routerId, externalIp);
+
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.DNAT_TABLE, flowRef,
+ NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_DNAT_TABLE, null, null);
+
+ return flowEntity;
+
+ }
+
+ private FlowEntity buildPreSNATDeleteFlowEntity(BigInteger dpId, String internalIp, long routerId, String externalIp) {
+
+ LOG.info("Building Delete PSNAT Flow entity for ip {} ", internalIp);
+
+ String flowRef = NatUtil.getFlowRef(dpId, NatConstants.PSNAT_TABLE, routerId, internalIp);
+
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
+ NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_DNAT_TABLE, null, null);
+
+ return flowEntity;
+ }
+
+ private FlowEntity buildSNATDeleteFlowEntity(BigInteger dpId, String internalIp, long routerId, String externalIp) {
+
+ LOG.info("Building Delete SNAT Flow entity for ip {} ", internalIp);
+
+ String flowRef = NatUtil.getFlowRef(dpId, NatConstants.SNAT_TABLE, routerId, internalIp);
+
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.SNAT_TABLE, flowRef,
+ NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_DNAT_TABLE, null, null);
+
+ return flowEntity;
+
+
+ }
+}
+
--- /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.natservice.internal;
+
+public class IPAddress {
+
+ private String ipAddress;
+ private int prefixLength;
+
+ public String getIpAddress() {
+ return ipAddress;
+ }
+ public int getPrefixLength() {
+ return prefixLength;
+ }
+
+ public IPAddress(String ipAddress, int prefixLength) {
+ this.ipAddress = ipAddress;
+ this.prefixLength = prefixLength;
+ }
+}
\ 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.natservice.internal;
+
+import com.google.common.collect.Lists;
+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.*;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.vpnservice.mdsalutil.packet.IPProtocols;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+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.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.NaptSwitches;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.RouterPorts;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.Ports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.ports.IpMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ProtocolTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.ip.port.map.IpPortExternal;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.GetFixedIPsForNeutronPortInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.GetFixedIPsForNeutronPortOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.NeutronvpnService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class InterfaceStateEventListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateEventListener.class);
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker dataBroker;
+ private IMdsalApiManager mdsalManager;
+ private FloatingIPListener floatingIPListener;
+ private NaptManager naptManager;
+ private NeutronvpnService neutronVpnService;
+
+ public InterfaceStateEventListener(final DataBroker db){
+ super(Interface.class);
+ dataBroker = db;
+ registerListener(db);
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ public void setFloatingIpListener(FloatingIPListener floatingIPListener) {
+ this.floatingIPListener = floatingIPListener;
+ }
+
+ public void setNeutronVpnService(NeutronvpnService neutronVpnService) {
+ this.neutronVpnService = neutronVpnService;
+ }
+
+ public void setNaptManager(NaptManager naptManager) {
+ this.naptManager = naptManager;
+
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), InterfaceStateEventListener.this, AsyncDataBroker.DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("Interface DataChange listener registration failed", e);
+ throw new IllegalStateException("Nexthop Manager registration Listener failed.", e);
+ }
+ }
+
+ private InstanceIdentifier<Interface> getWildCardPath() {
+ return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Interface> identifier, Interface delintrf) {
+ LOG.trace("NAT Service : Interface {} removed event received", delintrf);
+ try {
+ if (delintrf != null) {
+ String interfaceName = delintrf.getName();
+ LOG.trace("NAT Service : Port removed event received for interface {} ", interfaceName);
+
+ BigInteger dpnId = NatUtil.getDpIdFromInterface(delintrf);
+ LOG.trace("NAT Service : PORT_REMOVE: Interface {} down in Dpn {}", interfaceName, dpnId);
+
+ String routerName = getRouterIdForPort(dataBroker, interfaceName);
+ if (routerName != null) {
+ processInterfaceRemoved(interfaceName, routerName);
+ removeSnatEntriesForPort(interfaceName,routerName);
+ } else {
+ LOG.debug("NAT Service : PORT_REMOVE: Router Id is null either Interface {} is not associated " +
+ "to router or failed to retrieve routerId due to exception", interfaceName);
+ }
+ }
+ } catch(Exception e) {
+ LOG.error("NAT Service : Exception caught in InterfaceOperationalStateRemove : {}", e);
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Interface> identifier, Interface original, Interface update) {
+ LOG.trace("NAT Service : Operation Interface update event - Old: {}, New: {}", original, update);
+ String interfaceName = update.getName();
+ if (update.getOperStatus().equals(Interface.OperStatus.Up)) {
+ LOG.trace("NAT Service : Port UP event received for interface {} ", interfaceName);
+ } else if (update.getOperStatus().equals(Interface.OperStatus.Down)) {
+ try {
+ LOG.trace("NAT Service : Port DOWN event received for interface {} ", interfaceName);
+
+ BigInteger dpnId = NatUtil.getDpIdFromInterface(update);
+ LOG.trace("NAT Service : PORT_DOWN: Interface {} down in Dpn {}", interfaceName, dpnId);
+
+ String routerName = getRouterIdForPort(dataBroker, interfaceName);
+ if (routerName != null) {
+ removeSnatEntriesForPort(interfaceName,routerName);
+ } else {
+ LOG.debug("NAT Service : PORT_DOWN: Router Id is null, either Interface {} is not associated " +
+ "to router or failed to retrieve routerId due to exception", interfaceName);
+ }
+ } catch (Exception ex) {
+ LOG.error("NAT Service : Exception caught in InterfaceOperationalStateDown : {}",ex);
+ }
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
+ LOG.trace("NAT Service : Interface {} up event received", intrf);
+ try {
+ String interfaceName = intrf.getName();
+ LOG.trace("NAT Service : Port added event received for interface {} ", interfaceName);
+ String routerId = getRouterIdForPort(dataBroker,interfaceName);
+ if (routerId != null) {
+ processInterfaceAdded(interfaceName, routerId);
+ }
+ } catch (Exception ex) {
+ LOG.error("NAT Service : Exception caught in Interface Operational State Up event: {}", ex);
+ }
+ }
+
+ private void removeSnatEntriesForPort(String interfaceName,String routerName) {
+ Long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ if (routerId == NatConstants.INVALID_ID) {
+ LOG.error("NAT Service : routerId not found for routername {}",routerName);
+ return;
+ }
+ BigInteger naptSwitch = getNaptSwitchforRouter(dataBroker,routerName);
+ if (naptSwitch == null) {
+ LOG.error("NAT Service : NaptSwitch is not elected for router {} with Id {}",routerName,routerId);
+ return;
+ }
+ //getInternalIp for port
+ List<String> fixedIps = getFixedIpsForPort(interfaceName);
+ if (fixedIps == null) {
+ LOG.debug("NAT Service : Internal Ips not found for InterfaceName {} in router {} with id {}",interfaceName,routerName,routerId);
+ return;
+ }
+ List<ProtocolTypes> protocolTypesList = getPortocolList();
+ for (String internalIp : fixedIps) {
+ LOG.debug("NAT Service : Internal Ip retrieved for interface {} is {} in router with Id {}",interfaceName,internalIp,routerId);
+ for(ProtocolTypes protocol : protocolTypesList) {
+ List<Integer> portList = NatUtil.getInternalIpPortListInfo(dataBroker, routerId, internalIp, protocol);
+ if (portList != null) {
+ for (Integer portnum : portList) {
+ //build and remove the flow in outbound table
+ try {
+ removeNatFlow(naptSwitch, NatConstants.OUTBOUND_NAPT_TABLE, routerId, internalIp, portnum);
+ } catch (Exception ex) {
+ LOG.error("NAT Service : Failed to remove snat flow for internalIP {} with Port {} protocol {} for routerId {} " +
+ "in OUTBOUNDTABLE of NaptSwitch {}: {}",internalIp,portnum,protocol,routerId,naptSwitch,ex);
+ }
+ //Get the external IP address and the port from the model
+ NAPTEntryEvent.Protocol proto = protocol.toString().equals(ProtocolTypes.TCP.toString()) ? NAPTEntryEvent.Protocol.TCP : NAPTEntryEvent.Protocol.UDP;
+ IpPortExternal ipPortExternal = NatUtil.getExternalIpPortMap(dataBroker, routerId,
+ internalIp, String.valueOf(portnum), proto);
+ if (ipPortExternal == null) {
+ LOG.error("Mapping for internalIp {} with port {} is not found in router with Id {}",internalIp,portnum,routerId);
+ return;
+ }
+ String externalIpAddress = ipPortExternal.getIpAddress();
+ Integer portNumber = ipPortExternal.getPortNum();
+
+ //build and remove the flow in inboundtable
+ try {
+ removeNatFlow(naptSwitch, NatConstants.INBOUND_NAPT_TABLE,routerId, externalIpAddress, portNumber);
+ } catch (Exception ex) {
+ LOG.error("NAT Service : Failed to remove snat flow internalIP {} with Port {} protocol {} for routerId {} " +
+ "in INBOUNDTABLE of naptSwitch {} : {}",externalIpAddress,portNumber,protocol,routerId,naptSwitch,ex);
+ }
+
+ String internalIpPort = internalIp + ":" + portnum;
+ // delete the entry from IntExtIpPortMap DS
+ try {
+ naptManager.removeFromIpPortMapDS(routerId, internalIpPort, proto);
+ naptManager.removePortFromPool(internalIpPort,externalIpAddress);
+ } catch (Exception ex){
+ LOG.error("NAPT Service : releaseIpExtPortMapping failed, Removal of ipportmap {} for router {} failed {}" ,
+ internalIpPort, routerId, ex);
+ }
+ }
+ // delete the entry from SnatIntIpPortMap DS
+ LOG.debug("NAT Service : Removing InternalIp :{} portlist :{} for protocol :{} of router {}",internalIp,portList,protocol,routerId);
+ naptManager.removeFromSnatIpPortDS(routerId,internalIp);
+ } else {
+ LOG.debug("NAT Service : No {} session for interface {} with internalIP {} in router with id {}",protocol,interfaceName,internalIp,routerId);
+ }
+ }
+ }
+ }
+
+ private String getRouterIdForPort(DataBroker dataBroker,String interfaceName) {
+ String vpnName = null, routerName = null;
+ if (NatUtil.isVpnInterfaceConfigured(dataBroker, interfaceName)) {
+ //getVpnInterface
+ VpnInterface vpnInterface = null;
+ try {
+ vpnInterface = NatUtil.getConfiguredVpnInterface(dataBroker, interfaceName);
+ } catch (Exception ex) {
+ LOG.error("NAT Service : Unable to process for interface {} as it is not configured", interfaceName);
+ }
+ if (vpnInterface != null) {
+ //getVpnName
+ try {
+ vpnName = vpnInterface.getVpnInstanceName();
+ LOG.debug("NAT Service : Retrieved VpnName {}", vpnName);
+ } catch (Exception e) {
+ LOG.error("NAT Service : Unable to get vpnname for vpninterface {} - {}", vpnInterface, e);
+ }
+ if (vpnName != null) {
+ try {
+ routerName = NatUtil.getRouterIdfromVpnId(dataBroker, vpnName);
+ } catch (Exception e) {
+ LOG.error("NAT Service : Unable to get routerId for vpnName {} - {}", vpnName, e);
+ }
+ if (routerName != null) {
+ //check router is associated to external network
+ if (NatUtil.isSnatEnabledForRouterId(dataBroker, routerName)) {
+ LOG.debug("NAT Service : Retreived Router Id {} for vpnname {} associated to interface {}",
+ routerName,vpnName,interfaceName);
+ return routerName;
+ } else {
+ LOG.info("NAT Service : Interface {} associated to routerId {} is not associated to external network",
+ interfaceName, routerName);
+ }
+ } else {
+ LOG.debug("Router is not associated to vpnname {} for interface {}",vpnName,interfaceName);
+ }
+ } else {
+ LOG.debug("NAT Service : vpnName not found for vpnInterface {} of port {}",vpnInterface,interfaceName);
+ }
+ }
+ } else {
+ LOG.debug("NAT Service : Interface {} is not a vpninterface",interfaceName);
+ }
+ return null;
+ }
+
+ private List<ProtocolTypes> getPortocolList() {
+ List<ProtocolTypes> protocollist = Lists.newArrayList();
+ protocollist.add(ProtocolTypes.TCP);
+ protocollist.add(ProtocolTypes.UDP);
+ return protocollist;
+ }
+
+ private BigInteger getNaptSwitchforRouter(DataBroker broker,String routerName) {
+ InstanceIdentifier<RouterToNaptSwitch> rtrNaptSw = InstanceIdentifier.builder(NaptSwitches.class).child
+ (RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
+ Optional<RouterToNaptSwitch> routerToNaptSwitchData = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, rtrNaptSw);
+ if (routerToNaptSwitchData.isPresent()) {
+ RouterToNaptSwitch routerToNaptSwitchInstance = routerToNaptSwitchData.get();
+ return routerToNaptSwitchInstance.getPrimarySwitchId();
+ }
+ return null;
+ }
+
+ private void removeNatFlow(BigInteger dpnId, short tableId,Long routerId, String ipAddress,int ipPort) {
+
+ String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, tableId, String.valueOf(routerId), ipAddress, ipPort);
+ FlowEntity snatFlowEntity = NatUtil.buildFlowEntity(dpnId, tableId, switchFlowRef);
+
+ mdsalManager.removeFlow(snatFlowEntity);
+ LOG.debug("NAT Service : Removed the flow in table {} for the switch with the DPN ID {} for router {} ip {} port {}",
+ tableId,dpnId,routerId,ipAddress,ipPort);
+ }
+
+ private void processInterfaceAdded(String portName, String rtrId) {
+ LOG.trace("Processing Interface Add Event for interface {}", portName);
+ String routerId = getRouterIdForPort(dataBroker, portName);
+ List<IpMapping> ipMappingList = getIpMappingForPortName(portName, routerId);
+ if (ipMappingList == null || ipMappingList.isEmpty()) {
+ LOG.trace("Ip Mapping list is empty/null for portname {}", portName);
+ return;
+ }
+ InstanceIdentifier<RouterPorts> pIdentifier = NatUtil.buildRouterPortsIdentifier(routerId);
+ for (IpMapping ipMapping : ipMappingList) {
+ floatingIPListener.createNATFlowEntries(portName, ipMapping, pIdentifier, routerId);
+ }
+ }
+
+ private void processInterfaceRemoved(String portName, String rtrId) {
+ LOG.trace("Processing Interface Removed Event for interface {}", portName);
+ String routerId = getRouterIdForPort(dataBroker, portName);
+ List<IpMapping> ipMappingList = getIpMappingForPortName(portName, routerId);
+ if (ipMappingList == null || ipMappingList.isEmpty()) {
+ LOG.trace("Ip Mapping list is empty/null for portName {}", portName);
+ return;
+ }
+ InstanceIdentifier<RouterPorts> pIdentifier = NatUtil.buildRouterPortsIdentifier(routerId);
+ for (IpMapping ipMapping : ipMappingList) {
+ floatingIPListener.removeNATFlowEntries(portName, ipMapping, pIdentifier, routerId);
+ }
+ }
+
+ private List<IpMapping> getIpMappingForPortName(String portName, String routerId) {
+ InstanceIdentifier<Ports> portToIpMapIdentifier = NatUtil.buildPortToIpMapIdentifier(routerId, portName);
+ Optional<Ports> port = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, portToIpMapIdentifier);
+ if(!port.isPresent()) {
+ LOG.error("NAT Service : Unable to read router port entry for router ID {} and port name {}", routerId, portName);
+ return null;
+ }
+ List<IpMapping> ipMappingList = port.get().getIpMapping();
+ return ipMappingList;
+ }
+
+ private List<String> getFixedIpsForPort (String interfname) {
+ LOG.debug("getFixedIpsForPort method is called for interface {}",interfname);
+ try {
+ Future<RpcResult<GetFixedIPsForNeutronPortOutput>> result =
+ neutronVpnService.getFixedIPsForNeutronPort(new GetFixedIPsForNeutronPortInputBuilder()
+ .setPortId(new Uuid(interfname)).build());
+
+ RpcResult<GetFixedIPsForNeutronPortOutput> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("NAT Service : RPC Call to GetFixedIPsForNeutronPortOutput returned with Errors {}", rpcResult.getErrors());
+ } else {
+ return rpcResult.getResult().getFixedIPs();
+ }
+ } catch (InterruptedException | ExecutionException | NullPointerException ex ) {
+ LOG.error("NAT Service : Exception while receiving fixedIps for port {}",interfname);
+ }
+ return null;
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("NAT Service : Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("NAT Service : Interface listener Closed");
+ }
+}
\ 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.natservice.internal;
+
+
+public class NAPTEntryEvent {
+ private String ipAddress;
+ private int portNumber;
+ private Long routerId;
+ private Operation op;
+ private Protocol protocol;
+
+ public String getIpAddress() {
+ return ipAddress;
+ }
+
+ public int getPortNumber() {
+ return portNumber;
+ }
+
+ public Long getRouterId() {
+ return routerId;
+ }
+
+ public Operation getOperation() {
+ return op;
+ }
+
+ public Protocol getProtocol() {
+ return protocol;
+ }
+
+ NAPTEntryEvent(String ipAddress, int portNumber, Long routerId, Operation op, Protocol protocol){
+ this.ipAddress = ipAddress;
+ this.portNumber = portNumber;
+ this.routerId = routerId;
+ this.op = op;
+ this.protocol = protocol;
+ }
+
+ public enum Operation{
+ ADD, DELETE;
+ }
+
+ public enum Protocol{
+ TCP, UDP;
+ }
+}
--- /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.natservice.internal;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ExtRouters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.NaptSwitches;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.NaptSwitchesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class NAPTSwitchSelector {
+ private static final Logger LOG = LoggerFactory.getLogger(NAPTSwitchSelector.class);
+
+ private DataBroker dataBroker;
+ public NAPTSwitchSelector(DataBroker dataBroker) {
+ this.dataBroker = dataBroker;
+ }
+
+ BigInteger selectNewNAPTSwitch(String routerName) {
+ LOG.info("NAT Service : Select a new NAPT switch for router {}", routerName);
+ Map<BigInteger, Integer> naptSwitchWeights = constructNAPTSwitches();
+ List<BigInteger> routerSwitches = getDpnsForVpn(routerName);
+ if(routerSwitches == null || routerSwitches.isEmpty()) {
+ LOG.debug("NAT Service : No switches are part of router {}", routerName);
+ LOG.error("NAT Service : NAPT SWITCH SELECTION STOPPED DUE TO NO DPNS SCENARIO FOR ROUTER {}", routerName);
+ return BigInteger.ZERO;
+ }
+
+ Set<SwitchWeight> switchWeights = new TreeSet<>();
+ for(BigInteger dpn : routerSwitches) {
+ if(naptSwitchWeights.get(dpn) != null) {
+ switchWeights.add(new SwitchWeight(dpn, naptSwitchWeights.get(dpn)));
+ } else {
+ switchWeights.add(new SwitchWeight(dpn, 0));
+ }
+ }
+
+ BigInteger primarySwitch;
+
+ if(!switchWeights.isEmpty()) {
+
+ LOG.debug("NAT Service : Current switch weights for router {} - {}", routerName, switchWeights);
+
+ Iterator<SwitchWeight> it = switchWeights.iterator();
+ RouterToNaptSwitchBuilder routerToNaptSwitchBuilder = new RouterToNaptSwitchBuilder().setRouterName(routerName);
+ if ( switchWeights.size() == 1 )
+ {
+ SwitchWeight singleSwitchWeight = null;
+ while(it.hasNext() ) {
+ singleSwitchWeight = it.next();
+ }
+ primarySwitch = singleSwitchWeight.getSwitch();
+ RouterToNaptSwitch id = routerToNaptSwitchBuilder.setPrimarySwitchId(primarySwitch).build();
+
+ MDSALUtil.syncWrite( dataBroker, LogicalDatastoreType.OPERATIONAL, getNaptSwitchesIdentifier(routerName), id);
+
+ LOG.debug( "NAT Service : successful addition of RouterToNaptSwitch to napt-switches container for single switch" );
+ return primarySwitch;
+ }
+ else
+ {
+ SwitchWeight firstSwitchWeight = null;
+ while(it.hasNext() ) {
+ firstSwitchWeight = it.next();
+ }
+ primarySwitch = firstSwitchWeight.getSwitch();
+ RouterToNaptSwitch id = routerToNaptSwitchBuilder.setPrimarySwitchId(primarySwitch).build();
+
+ MDSALUtil.syncWrite( dataBroker, LogicalDatastoreType.OPERATIONAL, getNaptSwitchesIdentifier(routerName), id);
+
+ LOG.debug( "NAT Service : successful addition of RouterToNaptSwitch to napt-switches container");
+ return primarySwitch;
+ }
+ } else {
+
+ primarySwitch = BigInteger.ZERO;
+
+ LOG.debug("NAT Service : switchWeights empty, primarySwitch: {} ", primarySwitch);
+ return primarySwitch;
+ }
+
+
+ }
+
+ private Map<BigInteger, Integer> constructNAPTSwitches() {
+ Optional<NaptSwitches> optNaptSwitches = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, getNaptSwitchesIdentifier());
+ Map<BigInteger, Integer> switchWeights = new HashMap<>();
+
+ if(optNaptSwitches.isPresent()) {
+ NaptSwitches naptSwitches = optNaptSwitches.get();
+ List<RouterToNaptSwitch> routerToNaptSwitches = naptSwitches.getRouterToNaptSwitch();
+
+ for(RouterToNaptSwitch naptSwitch : routerToNaptSwitches) {
+ BigInteger primarySwitch = naptSwitch.getPrimarySwitchId();
+ //update weight
+ Integer weight = switchWeights.get(primarySwitch);
+ if(weight == null) {
+ switchWeights.put(primarySwitch, 1);
+ } else {
+ switchWeights.put(primarySwitch, ++weight);
+ }
+ }
+ }
+ return switchWeights;
+ }
+
+ private InstanceIdentifier<NaptSwitches> getNaptSwitchesIdentifier() {
+ return InstanceIdentifier.create(NaptSwitches.class);
+ }
+
+ private InstanceIdentifier<RouterToNaptSwitch> getNaptSwitchesIdentifier(String routerName) {
+ return InstanceIdentifier.builder(NaptSwitches.class).child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerName)).build();
+ }
+
+ public List<BigInteger> getDpnsForVpn(String routerName ) {
+ LOG.debug( "NAT Service : getVpnToDpnList called for RouterName {}", routerName );
+ long bgpVpnId = NatUtil.getBgpVpnId(dataBroker, routerName);
+ if(bgpVpnId != NatConstants.INVALID_ID){
+ return NatUtil.getDpnsForRouter(dataBroker, routerName);
+ }
+ InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.builder(VpnInstanceOpData.class)
+ .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(routerName))
+ .build();
+
+ List<BigInteger> dpnsInVpn = new ArrayList<>();
+ Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = NatUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
+
+ if(vpnInstanceOpData.isPresent()) {
+ LOG.debug( "NAT Service : getVpnToDpnList able to fetch vpnInstanceOpData" );
+ VpnInstanceOpDataEntry vpnInstanceOpDataEntry = vpnInstanceOpData.get();
+ List<VpnToDpnList> vpnDpnList = vpnInstanceOpDataEntry.getVpnToDpnList();
+ if(vpnDpnList != null) {
+ for(VpnToDpnList vpnToDpn: vpnDpnList) {
+ dpnsInVpn.add(vpnToDpn.getDpnId());
+ }
+ }
+ }
+
+ if(dpnsInVpn == null || dpnsInVpn.isEmpty()) {
+ LOG.debug("NAT Service : Unable to get the switches for the router {} from the VPNInstanceOpData", routerName);
+ dpnsInVpn = NatUtil.getDpnsForRouter(dataBroker, routerName);
+ if(dpnsInVpn == null || dpnsInVpn.isEmpty()){
+ LOG.debug("NAT Service : No switches are part of router {}", routerName);
+ return dpnsInVpn;
+ }
+ }
+
+ LOG.debug( "NAT Service : getVpnToDpnList returning vpnDpnList {}", dpnsInVpn);
+ return dpnsInVpn;
+
+
+ }
+
+ private static class SwitchWeight implements Comparable<SwitchWeight>
+ {
+ private BigInteger swich;
+ private int weight;
+
+ public SwitchWeight( BigInteger swich, int weight )
+ {
+ this.swich = swich;
+ this.weight = weight;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((swich == null) ? 0 : swich.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ SwitchWeight other = (SwitchWeight) obj;
+ if (swich == null) {
+ if (other.swich != null)
+ return false;
+ } else if (!swich.equals(other.swich))
+ return false;
+ return true;
+ }
+
+ public BigInteger getSwitch() {
+ return swich;
+ }
+
+ public int getWeight() {
+ return weight;
+ }
+
+ public void incrementWeight() {
+ ++ weight;
+ }
+
+ @Override
+ public int compareTo(SwitchWeight o) {
+ return o.getWeight() - weight;
+ }
+ }
+}
--- /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.natservice.internal;
+
+import org.opendaylight.vpnservice.mdsalutil.*;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.vpnservice.mdsalutil.packet.IPProtocols;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.ArrayList;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NaptEventHandler {
+ private NaptManager naptManager;
+ private static final Logger LOG = LoggerFactory.getLogger(NaptEventHandler.class);
+ private static IMdsalApiManager mdsalManager;
+ private DataBroker dataBroker;
+
+ public NaptEventHandler(final DataBroker dataBroker) {
+ this.dataBroker = dataBroker;
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ public void setNaptManager(NaptManager naptManager) {
+ this.naptManager = naptManager;
+ }
+
+
+ public void handleEvent(NAPTEntryEvent naptEntryEvent){
+ /*
+ Flow programming logic of the OUTBOUND NAPT TABLE :
+ 1) Get the internal IP address, port number, router ID from the event.
+ 2) Use the NAPT service getExternalAddressMapping() to get the External IP and the port.
+ 3) Build the flow for replacing the Internal IP and port with the External IP and port.
+ a) Write the matching criteria.
+ b) Match the router ID in the metadata.
+ d) Write the VPN ID to the metadata.
+ e) Write the other data.
+ f) Set the apply actions instruction with the action setfield.
+ 4) Write the flow to the OUTBOUND NAPT Table and forward to FIB table for routing the traffic.
+
+ Flow programming logic of the INBOUND NAPT TABLE :
+ Same as Outbound table logic except that :
+ 1) Build the flow for replacing the External IP and port with the Internal IP and port.
+ 2) Match the VPN ID in the metadata.
+ 3) Write the router ID to the metadata.
+ 5) Write the flow to the INBOUND NAPT Table and forward to FIB table for routing the traffic.
+ */
+ Long routerId = naptEntryEvent.getRouterId();
+ LOG.info("NAT Service : handleEvent() entry for IP {}, port {}, routerID {}", naptEntryEvent.getIpAddress(), naptEntryEvent.getPortNumber(), routerId);
+
+ //Get the DPN ID
+ BigInteger dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
+ long bgpVpnId = NatConstants.INVALID_ID;
+ if(dpnId == null ){
+ LOG.warn("NAT Service : dpnId is null. Assuming the router ID {} as the BGP VPN ID and proceeding....", routerId);
+ bgpVpnId = routerId;
+ LOG.debug("NAT Service : BGP VPN ID {}", bgpVpnId);
+ String vpnName = NatUtil.getRouterName(dataBroker, bgpVpnId);
+ String routerName = NatUtil.getRouterIdfromVpnId(dataBroker, vpnName);
+ routerId = NatUtil.getVpnId(dataBroker, routerName);
+ LOG.debug("NAT Service : Router ID {}", routerId);
+ dpnId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
+ if(dpnId == null){
+ LOG.error("NAT Service : dpnId is null for the router {}", routerId);
+ return;
+ }
+ }
+ if(naptEntryEvent.getOperation() == NAPTEntryEvent.Operation.ADD) {
+ LOG.debug("NAT Service : Inside Add operation of NaptEventHandler");
+
+ //Get the external network ID from the ExternalRouter model
+ Uuid networkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
+ if(networkId == null ){
+ LOG.error("NAT Service : networkId is null");
+ return;
+ }
+
+ //Get the VPN ID from the ExternalNetworks model
+ Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
+ if(vpnUuid == null ){
+ LOG.error("NAT Service : vpnUuid is null");
+ return;
+ }
+ Long vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
+
+ //Get the internal IpAddress, internal port number from the event
+ String internalIpAddress = naptEntryEvent.getIpAddress();
+ int internalPort = naptEntryEvent.getPortNumber();
+ SessionAddress internalAddress = new SessionAddress(internalIpAddress, internalPort);
+ NAPTEntryEvent.Protocol protocol = naptEntryEvent.getProtocol();
+
+ //Get the external IP address for the corresponding internal IP address
+ SessionAddress externalAddress = naptManager.getExternalAddressMapping(routerId, internalAddress, naptEntryEvent.getProtocol());
+ if(externalAddress == null ){
+ if(externalAddress == null){
+ LOG.error("NAT Service : externalAddress is null");
+ return;
+ }
+ }
+ //Build and install the NAPT translation flows in the Outbound and Inbound NAPT tables
+ buildAndInstallNatFlows(dpnId, NatConstants.OUTBOUND_NAPT_TABLE, vpnId, routerId, bgpVpnId, internalAddress, externalAddress, protocol);
+ buildAndInstallNatFlows(dpnId, NatConstants.INBOUND_NAPT_TABLE, vpnId, routerId, bgpVpnId, externalAddress, internalAddress, protocol);
+
+ }else{
+ LOG.debug("NAT Service : Inside delete Operation of NaptEventHandler");
+ removeNatFlows(dpnId, NatConstants.INBOUND_NAPT_TABLE, routerId, naptEntryEvent.getIpAddress(), naptEntryEvent.getPortNumber());
+ }
+
+ LOG.info("NAT Service : handleNaptEvent() exited for IP, port, routerID : {}", naptEntryEvent.getIpAddress(), naptEntryEvent.getPortNumber(), routerId);
+ }
+
+ public static void buildAndInstallNatFlows(BigInteger dpnId, short tableId, long vpnId, long routerId, long bgpVpnId, SessionAddress actualSourceAddress,
+ SessionAddress translatedSourceAddress, NAPTEntryEvent.Protocol protocol){
+ LOG.debug("NAT Service : Build and install NAPT flows in InBound and OutBound tables for dpnId {} and routerId {}", dpnId, routerId);
+ //Build the flow for replacing the actual IP and port with the translated IP and port.
+ String actualIp = actualSourceAddress.getIpAddress();
+ int actualPort = actualSourceAddress.getPortNumber();
+ String translatedIp = translatedSourceAddress.getIpAddress();
+ String translatedPort = String.valueOf(translatedSourceAddress.getPortNumber());
+ int idleTimeout=0;
+ if(tableId == NatConstants.OUTBOUND_NAPT_TABLE) {
+ idleTimeout = NatConstants.DEFAULT_NAPT_IDLE_TIMEOUT;
+ }
+ long metaDataValue = routerId;
+ String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, tableId, String.valueOf(metaDataValue), actualIp, actualPort);
+
+ long intranetVpnId;
+ if(bgpVpnId != NatConstants.INVALID_ID){
+ intranetVpnId = bgpVpnId;
+ }else{
+ intranetVpnId = routerId;
+ }
+ LOG.debug("NAT Service : Intranet VPN ID {}", intranetVpnId);
+ LOG.debug("NAT Service : Router ID {}", routerId);
+ FlowEntity snatFlowEntity = MDSALUtil.buildFlowEntity(dpnId, tableId, switchFlowRef, NatConstants.DEFAULT_NAPT_FLOW_PRIORITY, NatConstants.NAPT_FLOW_NAME,
+ idleTimeout, 0, NatUtil.getCookieNaptFlow(metaDataValue), buildAndGetMatchInfo(actualIp, actualPort, tableId, protocol, intranetVpnId, vpnId),
+ buildAndGetSetActionInstructionInfo(translatedIp, translatedPort, intranetVpnId, vpnId, tableId, protocol));
+
+ snatFlowEntity.setSendFlowRemFlag(true);
+
+ LOG.debug("NAT Service : Installing the NAPT flow in the table {} for the switch with the DPN ID {} ", tableId, dpnId);
+ mdsalManager.installFlow(snatFlowEntity);
+ }
+
+ private static List<MatchInfo> buildAndGetMatchInfo(String ip, int port, short tableId, NAPTEntryEvent.Protocol protocol, long segmentId, long vpnId){
+ MatchInfo ipMatchInfo = null;
+ MatchInfo portMatchInfo = null;
+ MatchInfo protocolMatchInfo = null;
+ InetAddress ipAddress = null;
+ String ipAddressAsString = null;
+ try {
+ ipAddress = InetAddress.getByName(ip);
+ ipAddressAsString = ipAddress.getHostAddress();
+
+ } catch (UnknownHostException e) {
+ LOG.error("NAT Service : UnknowHostException in buildAndGetMatchInfo. Failed to build NAPT Flow for ip {}", ipAddress);
+ return null;
+ }
+
+ MatchInfo metaDataMatchInfo = null;
+ if(tableId == NatConstants.OUTBOUND_NAPT_TABLE){
+ ipMatchInfo = new MatchInfo(MatchFieldType.ipv4_source, new String[] {ipAddressAsString, "32" });
+ if(protocol == NAPTEntryEvent.Protocol.TCP) {
+ protocolMatchInfo = new MatchInfo(MatchFieldType.ip_proto, new long[] {IPProtocols.TCP.intValue()});
+ portMatchInfo = new MatchInfo(MatchFieldType.tcp_src, new long[]{port});
+ } else if(protocol == NAPTEntryEvent.Protocol.UDP) {
+ protocolMatchInfo = new MatchInfo(MatchFieldType.ip_proto, new long[] {IPProtocols.UDP.intValue()});
+ portMatchInfo = new MatchInfo(MatchFieldType.udp_src, new long[]{port});
+ }
+ metaDataMatchInfo = new MatchInfo(MatchFieldType.metadata, new BigInteger[]{BigInteger.valueOf(segmentId), MetaDataUtil.METADATA_MASK_VRFID});
+ }else{
+ ipMatchInfo = new MatchInfo(MatchFieldType.ipv4_destination, new String[] {ipAddressAsString, "32" });
+ if(protocol == NAPTEntryEvent.Protocol.TCP) {
+ protocolMatchInfo = new MatchInfo(MatchFieldType.ip_proto, new long[] {IPProtocols.TCP.intValue()});
+ portMatchInfo = new MatchInfo(MatchFieldType.tcp_dst, new long[]{port});
+ } else if(protocol == NAPTEntryEvent.Protocol.UDP) {
+ protocolMatchInfo = new MatchInfo(MatchFieldType.ip_proto, new long[] {IPProtocols.UDP.intValue()});
+ portMatchInfo = new MatchInfo(MatchFieldType.udp_dst, new long[]{port});
+ }
+ //metaDataMatchInfo = new MatchInfo(MatchFieldType.metadata, new BigInteger[]{BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID});
+ }
+ ArrayList<MatchInfo> matchInfo = new ArrayList<>();
+ matchInfo.add(new MatchInfo(MatchFieldType.eth_type, new long[] { 0x0800L }));
+ matchInfo.add(ipMatchInfo);
+ matchInfo.add(protocolMatchInfo);
+ matchInfo.add(portMatchInfo);
+ if(tableId == NatConstants.OUTBOUND_NAPT_TABLE){
+ matchInfo.add(metaDataMatchInfo);
+ }
+ return matchInfo;
+ }
+
+ private static List<InstructionInfo> buildAndGetSetActionInstructionInfo(String ipAddress, String port, long segmentId, long vpnId, short tableId, NAPTEntryEvent.Protocol protocol) {
+ ActionInfo ipActionInfo = null;
+ ActionInfo portActionInfo = null;
+ ArrayList<ActionInfo> listActionInfo = new ArrayList<>();
+ ArrayList<InstructionInfo> instructionInfo = new ArrayList<>();
+
+ if(tableId == NatConstants.OUTBOUND_NAPT_TABLE){
+ ipActionInfo = new ActionInfo(ActionType.set_source_ip, new String[] {ipAddress});
+ if(protocol == NAPTEntryEvent.Protocol.TCP) {
+ portActionInfo = new ActionInfo( ActionType.set_tcp_source_port, new String[] {port});
+ } else if(protocol == NAPTEntryEvent.Protocol.UDP) {
+ portActionInfo = new ActionInfo( ActionType.set_udp_source_port, new String[] {port});
+ }
+ instructionInfo.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]{BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID}));
+ }else{
+ ipActionInfo = new ActionInfo(ActionType.set_destination_ip, new String[] {ipAddress});
+ if(protocol == NAPTEntryEvent.Protocol.TCP) {
+ portActionInfo = new ActionInfo( ActionType.set_tcp_destination_port, new String[] {port});
+ } else if(protocol == NAPTEntryEvent.Protocol.UDP) {
+ portActionInfo = new ActionInfo( ActionType.set_udp_destination_port, new String[] {port});
+ }
+ instructionInfo.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[]{BigInteger.valueOf(segmentId), MetaDataUtil.METADATA_MASK_VRFID}));
+ }
+
+ listActionInfo.add(ipActionInfo);
+ listActionInfo.add(portActionInfo);
+
+ instructionInfo.add(new InstructionInfo(InstructionType.apply_actions, listActionInfo));
+ instructionInfo.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.NAPT_PFIB_TABLE }));
+
+ return instructionInfo;
+ }
+
+ void removeNatFlows(BigInteger dpnId, short tableId ,long segmentId, String ip, int port){
+ if(dpnId == null || dpnId.equals(BigInteger.ZERO)){
+ LOG.error("NAT Service : DPN ID {} is invalid" , dpnId);
+ }
+ LOG.debug("NAT Service : Remove NAPT flows for dpnId {}, segmentId {}, ip {} and port {} ", dpnId, segmentId, ip, port);
+
+ //Build the flow with the port IP and port as the match info.
+ String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, tableId, String.valueOf(segmentId), ip, port);
+ FlowEntity snatFlowEntity = NatUtil.buildFlowEntity(dpnId, tableId, switchFlowRef);
+ LOG.debug("NAT Service : Remove the flow in the table {} for the switch with the DPN ID {}", NatConstants.INBOUND_NAPT_TABLE, dpnId);
+ mdsalManager.removeFlow(snatFlowEntity);
+
+ }
+
+}
--- /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.natservice.internal;
+
+import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeExperimenterErrorNotification;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.RemovedReasonFlags;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.TcpMatchFields;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.UdpMatchFields;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
+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.TcpMatch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatch;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.ip.port.map.IpPortExternal;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import java.math.BigInteger;
+
+public class NaptFlowRemovedEventHandler implements SalFlowListener{
+ private DataBroker dataBroker;
+ private final EventDispatcher naptEventdispatcher;
+ private static final Logger LOG = LoggerFactory.getLogger(NaptFlowRemovedEventHandler.class);
+ private final NaptPacketInHandler naptPacketInHandler;
+ private IMdsalApiManager mdsalManager;
+ private NaptManager naptManager;
+
+ public NaptFlowRemovedEventHandler(EventDispatcher eventDispatcher, DataBroker dataBroker, NaptPacketInHandler handler,
+ IMdsalApiManager mdsalManager, NaptManager naptManager) {
+ this.naptEventdispatcher = eventDispatcher;
+ this.dataBroker = dataBroker;
+ this.naptPacketInHandler = handler;
+ this.mdsalManager = mdsalManager;
+ this.naptManager = naptManager;
+ }
+
+ @Override
+ public void onSwitchFlowRemoved(SwitchFlowRemoved switchFlowRemoved) {
+
+/*
+ If the removed flow is from the OUTBOUND NAPT table :
+ 1) Get the ActionInfo of the flow.
+ 2) From the ActionInfo of the flow get the internal IP address, port and the protocol.
+ 3) Get the Metadata matching info of the flow.
+ 4) From the Metadata matching info of the flow get router ID.
+ 5) Querry the container intext-ip-port-map using the router ID
+ and the internal IP address, port to get the external IP address, port
+ 6) Instantiate an NaptEntry event and populate the external IP address, port and the router ID.
+ 7) Place the NaptEntry event to the queue.
+*/
+
+ short tableId = switchFlowRemoved.getTableId();
+ RemovedReasonFlags removedReasonFlag = switchFlowRemoved.getRemovedReason();
+
+ if (tableId == NatConstants.OUTBOUND_NAPT_TABLE && removedReasonFlag.isIDLETIMEOUT()) {
+ LOG.info("NaptFlowRemovedEventHandler : onSwitchFlowRemoved() entry");
+
+ //Get the internal internal IP address and the port number from the IPv4 match.
+ Ipv4Prefix internalIpv4Address = null;
+ Layer3Match layer3Match = switchFlowRemoved.getMatch().getLayer3Match();
+ if (layer3Match instanceof Ipv4Match) {
+ Ipv4Match internalIpv4Match = (Ipv4Match) layer3Match;
+ internalIpv4Address = internalIpv4Match.getIpv4Source();
+ }
+ if(internalIpv4Address == null){
+ LOG.error("NaptFlowRemovedEventHandler : Matching internal IP is null while retrieving the value from the Outbound NAPT flow");
+ return;
+ }
+ //Get the internal IP as a string
+ String internalIpv4AddressAsString = internalIpv4Address.getValue();
+ String[] internalIpv4AddressParts = internalIpv4AddressAsString.split("/");
+ String internalIpv4HostAddress = null;
+ if(internalIpv4AddressParts.length >= 1){
+ internalIpv4HostAddress = internalIpv4AddressParts[0];
+ }
+
+ //Get the protocol from the layer4 match
+ NAPTEntryEvent.Protocol protocol = null;
+ Integer internalPortNumber = null;
+ Layer4Match layer4Match = switchFlowRemoved.getMatch().getLayer4Match();
+ if (layer4Match instanceof TcpMatch) {
+ TcpMatchFields tcpMatchFields = (TcpMatchFields)layer4Match;
+ internalPortNumber = tcpMatchFields.getTcpSourcePort().getValue();
+ protocol = NAPTEntryEvent.Protocol.TCP;
+ }else if (layer4Match instanceof UdpMatch){
+ UdpMatchFields udpMatchFields = (UdpMatchFields)layer4Match;
+ internalPortNumber = udpMatchFields.getUdpSourcePort().getValue();
+ protocol = NAPTEntryEvent.Protocol.UDP;
+ }
+ if(protocol == null){
+ LOG.error("NaptFlowRemovedEventHandler : Matching protocol is null while retrieving the value from the Outbound NAPT flow");
+ return;
+ }
+
+ //Get the router ID from the metadata.
+ Long routerId;
+ BigInteger metadata = switchFlowRemoved.getMatch().getMetadata().getMetadata();
+ if(MetaDataUtil.getNatRouterIdFromMetadata(metadata) != 0) {
+ routerId = MetaDataUtil.getNatRouterIdFromMetadata(metadata);
+ }else {
+ LOG.error("NaptFlowRemovedEventHandler : Null exception while retrieving routerId");
+ return;
+ }
+
+ //Get the external IP address and the port from the model
+ IpPortExternal ipPortExternal = NatUtil.getExternalIpPortMap(dataBroker, routerId, internalIpv4HostAddress, internalPortNumber.toString(), protocol);
+ if(ipPortExternal == null){
+ LOG.error("NaptFlowRemovedEventHandler : IpPortExternal is null while querried from the model");
+ return;
+ }
+ String externalIpAddress = ipPortExternal.getIpAddress();
+ int externalPortNumber = ipPortExternal.getPortNum();
+
+ //Create an NAPT event and place it in the queue.
+ NAPTEntryEvent naptEntryEvent = new NAPTEntryEvent(externalIpAddress, externalPortNumber, routerId, NAPTEntryEvent.Operation.DELETE, protocol);
+ naptEventdispatcher.addNaptEvent(naptEntryEvent);
+
+ //Get the DPN ID from the Node
+ InstanceIdentifier<Node> nodeRef = switchFlowRemoved.getNode().getValue().firstIdentifierOf(Node.class);
+ String dpn = nodeRef.firstKeyOf(Node.class).getId().getValue();
+ BigInteger dpnId = getDpnId(dpn);
+ String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, tableId, String.valueOf(metadata), internalIpv4HostAddress, internalPortNumber);
+
+ //Inform the MDSAL manager to inform about the flow removal.
+ LOG.debug("NaptFlowRemovedEventHandler : DPN ID {}, Metadata {}, SwitchFlowRef {}, internalIpv4HostAddress{}", dpnId, metadata, switchFlowRef, internalIpv4AddressAsString);
+ FlowEntity snatFlowEntity = NatUtil.buildFlowEntity(dpnId, tableId, switchFlowRef);
+ mdsalManager.removeFlow(snatFlowEntity);
+
+ LOG.debug("Received flow removed notification due to idleTimeout of flow from switch for flowref {}",switchFlowRef);
+ //Remove the SourceIP:Port key from the Napt packet handler map.
+ String internalIpPortKey = internalIpv4HostAddress + ":" + internalPortNumber;
+ naptPacketInHandler.removeIncomingPacketMap(internalIpPortKey);
+
+ //Remove the mapping of internal fixed ip/port to external ip/port from the datastore.
+ SessionAddress internalSessionAddress = new SessionAddress(internalIpv4HostAddress, internalPortNumber);
+ naptManager.releaseIpExtPortMapping(routerId, internalSessionAddress, protocol);
+ LOG.info("NaptFlowRemovedEventHandler : onSwitchFlowRemoved() exit");
+ }else {
+ LOG.debug("Received flow removed notification due to flowdelete from switch for flowref");
+ }
+
+ }
+
+ private BigInteger getDpnId(String node) {
+ //openflow:1]
+ String temp[] = node.split(":");
+ BigInteger dpnId = new BigInteger(temp[1]);
+ return dpnId;
+
+ }
+
+ @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
+
+ }
+
+}
--- /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
+ */
+
+/*
+ * Created eyugsar 2016/12/1
+ */
+
+package org.opendaylight.vpnservice.natservice.internal;
+
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Future;
+import java.util.concurrent.ExecutionException;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.net.util.SubnetUtils;
+import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ext.routers.Routers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.ips.counter.ExternalCounters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.ips.counter.ExternalCountersKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounterKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMappingKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.IpPortMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolTypeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.ip.port.map.IpPortExternal;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.ip.port.map.IpPortExternalBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.IntipPortMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.IntipPortMapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPortKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounterBuilder;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.UncheckedExecutionException;
+
+public class NaptManager {
+ private static final Logger LOG = LoggerFactory.getLogger(NaptManager.class);
+ private final DataBroker broker;
+ private IdManagerService idManager;
+ private static final long LOW_PORT = 49152L;
+ private static final long HIGH_PORT = 65535L;
+ private static boolean EXTSUBNET_FLAG = false;
+ private static boolean NEXT_EXTIP_FLAG = false;
+
+ public NaptManager(final DataBroker db) {
+ this.broker = db;
+ }
+
+ public void setIdManager(IdManagerService idManager) {
+ this.idManager = idManager;
+ }
+
+ protected void createNaptPortPool(String PoolName) {
+ LOG.debug("NAPT Service : createPortPool requested for : {}", PoolName);
+ CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
+ .setPoolName(PoolName)
+ .setLow(LOW_PORT)
+ .setHigh(HIGH_PORT)
+ .build();
+ try {
+ Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
+ if ((result != null) && (result.get().isSuccessful())) {
+ LOG.debug("NAPT Service : Created PortPool");
+ } else {
+ LOG.error("NAPT Service : Unable to create PortPool");
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Failed to create PortPool for NAPT Service",e);
+ }
+ }
+
+ void removeNaptPortPool(String poolName) {
+ DeleteIdPoolInput deleteIdPoolInput = new DeleteIdPoolInputBuilder().setPoolName(poolName).build();
+ LOG.debug("NAPT Service : Remove Napt port pool requested for : {}", poolName);
+ try {
+ Future<RpcResult<Void>> result = idManager.deleteIdPool(deleteIdPoolInput);
+ if ((result != null) && (result.get().isSuccessful())) {
+ LOG.debug("NAPT Service : Deleted PortPool {}", poolName);
+ } else {
+ LOG.error("NAPT Service : Unable to delete PortPool {}", poolName);
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Failed to delete PortPool {} for NAPT Service", poolName, e);
+ }
+ }
+
+ // 1. napt service functions
+ /**
+ * this method is used to inform this service of what external IP address to be used
+ * as mapping when requested one for the internal IP address given in the input
+ * @param segmentId – segmentation in which the mapping to be used. Eg; routerid
+ * @param internal subnet prefix or ip address
+ * @param external subnet prefix or ip address
+ */
+
+ public void registerMapping(long segmentId, IPAddress internal, IPAddress external) {
+
+ LOG.debug("NAPT Service : registerMapping called with segmentid {}, internalIp {}, prefix {}, externalIp {} and prefix {} ", segmentId, internal.getIpAddress(),
+ internal.getPrefixLength(), external.getIpAddress(), external.getPrefixLength());
+ // Create Pool per ExternalIp and not for all IPs in the subnet. Create new Pools during getExternalAddressMapping if exhausted.
+ String externalIpPool;
+ if (external.getPrefixLength() !=0 && external.getPrefixLength() != NatConstants.DEFAULT_PREFIX) { // subnet case
+ String externalSubnet = new StringBuilder(64).append(external.getIpAddress()).append("/").append(external.getPrefixLength()).toString();
+ LOG.debug("NAPT Service : externalSubnet is : {}", externalSubnet);
+ SubnetUtils subnetUtils = new SubnetUtils(externalSubnet);
+ SubnetInfo subnetInfo = subnetUtils.getInfo();
+ externalIpPool = subnetInfo.getLowAddress();
+ } else { // ip case
+ externalIpPool = external.getIpAddress();
+ }
+ createNaptPortPool(externalIpPool);
+
+ // Store the ip to ip map in Operational DS
+ String internalIp = internal.getIpAddress();
+ if(internal.getPrefixLength() != 0) {
+ internalIp = new StringBuilder(64).append(internal.getIpAddress()).append("/").append(internal.getPrefixLength()).toString();
+ }
+ String externalIp = external.getIpAddress();
+ if(external.getPrefixLength() != 0) {
+ externalIp = new StringBuilder(64).append(external.getIpAddress()).append("/").append(external.getPrefixLength()).toString();
+ }
+ updateCounter(segmentId, externalIp, true);
+ //update the actual ip-map
+ IpMap ipm = new IpMapBuilder().setKey(new IpMapKey(internalIp)).setInternalIp(internalIp).setExternalIp(externalIp).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, getIpMapIdentifier(segmentId, internalIp), ipm);
+ LOG.debug("NAPT Service : registerMapping exit after updating DS with internalIP {}, externalIP {}", internalIp, externalIp);
+ }
+
+ public void updateCounter(long segmentId, String externalIp, boolean isAdd){
+ short counter = 0;
+ InstanceIdentifier<ExternalIpCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class).child(ExternalCounters.class, new ExternalCountersKey(segmentId)).child(ExternalIpCounter.class, new ExternalIpCounterKey(externalIp)).build();
+ Optional <ExternalIpCounter> externalIpCounter = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ if (externalIpCounter.isPresent()) {
+ counter = externalIpCounter.get().getCounter();
+ if(isAdd){
+ counter++;
+ LOG.debug("NAT Service : externalIp and counter after increment are {} and {}", externalIp, counter);
+ }else{
+ if(counter > 0){
+ counter--;
+ }
+ LOG.debug("NAT Service : externalIp and counter after decrement are {} and {}", externalIp, counter);
+ }
+
+ }else if(isAdd){
+ counter = 1;
+ }
+
+ //update the new counter value for this externalIp
+ ExternalIpCounter externalIpCounterData = new ExternalIpCounterBuilder().setKey(new ExternalIpCounterKey(externalIp)).setExternalIp(externalIp).setCounter(counter).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, getExternalIpsIdentifier(segmentId, externalIp), externalIpCounterData);
+
+ }
+
+ /**
+ * method to get external ip/port mapping when provided with internal ip/port pair
+ * If already a mapping exist for the given input, then the existing mapping is returned
+ * instead of overwriting with new ip/port pair.
+ * @param segmentId
+ * @param sourceAddress - internal ip address/port pair
+ * @return external ip address/port
+ */
+ public SessionAddress getExternalAddressMapping(long segmentId, SessionAddress sourceAddress, NAPTEntryEvent.Protocol protocol) {
+ LOG.debug("NAPT Service : getExternalAddressMapping called with segmentId {}, internalIp {} and port {}",
+ segmentId, sourceAddress.getIpAddress(), sourceAddress.getPortNumber());
+ /*
+ 1. Get Internal IP, Port in IP:Port format
+ 2. Inside DB with routerId get the list of entries and check if it matches with existing IP:Port
+ 3. If True return SessionAddress of ExternalIp and Port
+ 4. Else check ip Map and Form the ExternalIp and Port and update DB and then return ExternalIp and Port
+ */
+
+ //SessionAddress externalIpPort = new SessionAddress();
+ String internalIpPort = new StringBuilder(64).append(sourceAddress.getIpAddress()).append(":").append(sourceAddress.getPortNumber()).toString();
+
+ // First check existing Port Map.
+ SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol);
+ if(existingIpPort != null) {
+ // populate externalIpPort from IpPortMap and return
+ LOG.debug("NAPT Service : getExternalAddressMapping successfully returning existingIpPort as {} and {}", existingIpPort.getIpAddress(), existingIpPort.getPortNumber());
+ return existingIpPort;
+ } else {
+ // Now check in ip-map
+ String externalIp = checkIpMap(segmentId, sourceAddress.getIpAddress());
+ if(externalIp == null) {
+ LOG.error("NAPT Service : getExternalAddressMapping, Unexpected error, internal to external ip map does not exist");
+ return null;
+ } else {
+ /* Logic assuming internalIp is always ip and not subnet
+ * case 1: externalIp is ip
+ * a) goto externalIp pool and getPort and return
+ * b) else return error
+ * case 2: externalIp is subnet
+ * a) Take first externalIp and goto that Pool and getPort
+ * if port -> return
+ * else Take second externalIp and create that Pool and getPort
+ * if port ->return
+ * else
+ * Continue same with third externalIp till we exhaust subnet
+ * b) Nothing worked return error
+ */
+ SubnetUtils externalIpSubnet;
+ List<String> allIps = new ArrayList<String>();
+ String subnetPrefix = "/" + String.valueOf(NatConstants.DEFAULT_PREFIX);
+ if( !externalIp.contains(subnetPrefix) ) {
+ EXTSUBNET_FLAG = true;
+ externalIpSubnet = new SubnetUtils(externalIp);
+ allIps = Arrays.asList(externalIpSubnet.getInfo().getAllAddresses());
+ LOG.debug("NAPT Service : total count of externalIps available {}", externalIpSubnet.getInfo().getAddressCount());
+ } else {
+ LOG.debug("NAPT Service : getExternalAddress single ip case");
+ if(externalIp.contains(subnetPrefix)) {
+ String[] externalIpSplit = externalIp.split("/");
+ String extIp = externalIpSplit[0];
+ externalIp = extIp; //remove /32 what we got from checkIpMap
+ }
+ allIps.add(externalIp);
+ }
+
+ for(String extIp : allIps) {
+ LOG.info("NAPT Service : Looping externalIPs with externalIP now as {}", extIp);
+ if(NEXT_EXTIP_FLAG) {
+ createNaptPortPool(extIp);
+ LOG.debug("NAPT Service : Created Pool for next Ext IP {}", extIp);
+ }
+ AllocateIdInput getIdInput = new AllocateIdInputBuilder()
+ .setPoolName(extIp).setIdKey(internalIpPort)
+ .build();
+ try {
+ Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
+ RpcResult<AllocateIdOutput> rpcResult;
+ if ((result != null) && (result.get().isSuccessful())) {
+ LOG.debug("NAPT Service : Got id from idManager");
+ rpcResult = result.get();
+ } else {
+ LOG.error("NAPT Service : getExternalAddressMapping, idManager could not allocate id retry if subnet");
+ if(!EXTSUBNET_FLAG) {
+ LOG.error("NAPT Service : getExternalAddressMapping returning null for single IP case, may be ports exhausted");
+ return null;
+ }
+ LOG.debug("NAPT Service : Could be ports exhausted case, try with another externalIP if possible");
+ NEXT_EXTIP_FLAG = true;
+ continue;
+ }
+ int extPort= rpcResult.getResult().getIdValue().intValue();
+ SessionAddress externalIpPort = new SessionAddress(extIp, extPort);
+ // Write to ip-port-map before returning
+ IpPortExternalBuilder ipExt = new IpPortExternalBuilder();
+ IpPortExternal ipPortExt = ipExt.setIpAddress(extIp).setPortNum(extPort).build();
+ IpPortMap ipm = new IpPortMapBuilder().setKey(new IpPortMapKey(internalIpPort))
+ .setIpPortInternal(internalIpPort).setIpPortExternal(ipPortExt).build();
+ LOG.debug("NAPT Service : getExternalAddressMapping writing into ip-port-map with externalIP {} and port {}",
+ ipPortExt.getIpAddress(), ipPortExt.getPortNum());
+ try {
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
+ getIpPortMapIdentifier(segmentId, internalIpPort, protocol), ipm);
+ } catch (UncheckedExecutionException uee) {
+ LOG.error("NAPT Service : Failed to write into ip-port-map with exception {}", uee.getMessage() );
+ }
+
+ // Write to snat-internal-ip-port-info
+ String internalIpAddress = sourceAddress.getIpAddress();
+ int ipPort = sourceAddress.getPortNumber();
+ ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
+ List<Integer> portList = NatUtil.getInternalIpPortListInfo(broker,segmentId,internalIpAddress,protocolType);
+ if (portList == null) {
+ portList = Lists.newArrayList();
+ }
+ portList.add(ipPort);
+
+ IntIpProtoTypeBuilder builder = new IntIpProtoTypeBuilder();
+ IntIpProtoType intIpProtocolType = builder.setKey(new IntIpProtoTypeKey(protocolType)).setPorts(portList).build();
+ try {
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
+ NatUtil.buildSnatIntIpPortIdentifier(segmentId, internalIpAddress, protocolType), intIpProtocolType);
+ } catch (Exception ex) {
+ LOG.error("NAPT Service : Failed to write into snat-internal-ip-port-info with exception {}", ex.getMessage() );
+ }
+
+ LOG.debug("NAPT Service : getExternalAddressMapping successfully returning externalIP {} and port {}",
+ externalIpPort.getIpAddress(), externalIpPort.getPortNumber());
+ return externalIpPort;
+ } catch(InterruptedException | ExecutionException e) {
+ LOG.error("NAPT Service : getExternalAddressMapping, Exception caught {}",e);
+ return null;
+ }
+ }// end of for loop
+ }// end of else ipmap present
+ }// end of else check ipmap
+ LOG.error("NAPT Service: getExternalAddressMapping returning null, nothing worked or externalIPs exhausted");
+ return null;
+ }
+
+
+ /**
+ * release the existing mapping of internal ip/port to external ip/port pair
+ * if no mapping exist for given internal ip/port, it returns false
+ * @param segmentId
+ * @param address
+ * @return true if mapping exist and the mapping is removed successfully
+ */
+
+ public boolean releaseAddressMapping(long segmentId, SessionAddress address, NAPTEntryEvent.Protocol protocol) {
+
+ LOG.debug("NAPT Service : releaseAddressMapping called with segmentId {}, internalIP {}, port {}", segmentId, address.getIpAddress(), address.getPortNumber());
+ // delete entry from IpPort Map and IP Map if exists
+ String internalIpPort = new StringBuilder(64).append(address.getIpAddress()).append(":").append(address.getPortNumber()).toString();
+ SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol);
+ if(existingIpPort != null) {
+ // delete the entry from IpPortMap DS
+ try {
+ removeFromIpPortMapDS(segmentId, internalIpPort , protocol);
+ } catch (Exception e){
+ LOG.error("NAPT Service : releaseAddressMapping failed, Removal of ipportmap {} for router {} failed {}" , internalIpPort, segmentId, e);
+ return false;
+ }
+ } else {
+ LOG.error("NAPT Service : releaseAddressMapping failed, segmentId {} and internalIpPort {} not found in IpPortMap DS", segmentId, internalIpPort);
+ return false;
+ }
+ String existingIp = checkIpMap(segmentId, address.getIpAddress());
+ if(existingIp != null) {
+ // delete the entry from IpMap DS
+ try {
+ removeFromIpMapDS(segmentId, address.getIpAddress());
+ } catch (Exception e){
+ LOG.error("NAPT Service : Removal of ipmap {} for router {} failed {}" , address.getIpAddress(), segmentId, e);
+ return false;
+ }
+ //delete the entry from snatIntIpportinfo
+ try {
+ removeFromSnatIpPortDS(segmentId, address.getIpAddress());
+ } catch (Exception e){
+ LOG.error("NAPT Service : releaseAddressMapping failed, Removal of snatipportmap {} for router {} failed {}" , address.getIpAddress(), segmentId, e);
+ return false;
+ }
+ } else {
+ LOG.error("NAPT Service : releaseAddressMapping failed, segmentId {} and internalIpPort {} not found in IpMap DS", segmentId, internalIpPort);
+ return false;
+ }
+ // Finally release port from idmanager
+ removePortFromPool(internalIpPort, existingIpPort.getIpAddress());
+
+ LOG.debug("NAPT Service : Exit of releaseAddressMapping successfully for segmentId {} and internalIpPort {}", segmentId, internalIpPort);
+ return true;
+
+ }
+
+ protected void releaseIpExtPortMapping(long segmentId, SessionAddress address, NAPTEntryEvent.Protocol protocol) {
+ String internalIpPort = address.getIpAddress() + ":" + address.getPortNumber();
+ SessionAddress existingIpPort = checkIpPortMap(segmentId, internalIpPort, protocol);
+ if(existingIpPort != null) {
+ // delete the entry from IpPortMap DS
+ try {
+ removeFromIpPortMapDS(segmentId, internalIpPort , protocol);
+ // Finally release port from idmanager
+ removePortFromPool(internalIpPort, existingIpPort.getIpAddress());
+ } catch (Exception e){
+ LOG.error("NAPT Service : releaseAddressMapping failed, Removal of ipportmap {} for router {} failed {}" ,
+ internalIpPort, segmentId, e);
+ }
+ } else {
+ LOG.error("NAPT Service : releaseIpExtPortMapping failed, segmentId {} and internalIpPort {} not found in IpPortMap DS", segmentId, internalIpPort);
+ }
+
+ //delete the entry of port for InternalIp from snatIntIpportMappingDS
+ try {
+ removeSnatIntIpPortDS(segmentId,address, protocol);
+ } catch (Exception e){
+ LOG.error("NAPT Service : releaseSnatIpPortMapping failed, Removal of snatipportmap {} for router {} failed {}" ,
+ address.getIpAddress(), segmentId, e);
+ }
+ }
+
+ /**
+ * removes the internal ip to external ip mapping if present
+ * @param segmentId
+ * @return true if successfully removed
+ */
+ public boolean removeMapping(long segmentId) {
+ try {
+ removeIpMappingForRouterID(segmentId);
+ removeIpPortMappingForRouterID(segmentId);
+ removeIntIpPortMappingForRouterID(segmentId);
+ } catch (Exception e){
+ LOG.error("NAPT Service : Removal of IPMapping for router {} failed {}" , segmentId, e);
+ return false;
+ }
+
+ //TODO : This is when router is deleted then cleanup the entries in tables, ports etc - Delete scenarios
+ return false;
+ }
+
+ // 2. Utility functions
+ protected InstanceIdentifier<IpMap> getIpMapIdentifier(long segid, String internal) {
+ InstanceIdentifier<IpMap> id = InstanceIdentifier.builder(
+ IntextIpMap.class).child(IpMapping.class, new IpMappingKey(segid)).child(IpMap.class, new IpMapKey(internal)).build();
+ return id;
+ }
+
+ protected InstanceIdentifier<ExternalIpCounter> getExternalIpsIdentifier(long segmentId, String external) {
+ InstanceIdentifier<ExternalIpCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class).child(ExternalCounters.class, new ExternalCountersKey(segmentId))
+ .child(ExternalIpCounter.class, new ExternalIpCounterKey(external)).build();
+ return id;
+ }
+
+ public static List<IpMap> getIpMapList(DataBroker broker, Long routerId) {
+ InstanceIdentifier<IpMapping> id = getIpMapList(routerId);
+ Optional<IpMapping> ipMappingListData = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ if (ipMappingListData.isPresent()) {
+ IpMapping ipMapping = ipMappingListData.get();
+ return ipMapping.getIpMap();
+ }
+ return null;
+ }
+
+ protected static InstanceIdentifier<IpMapping> getIpMapList(long routerId) {
+ InstanceIdentifier<IpMapping> id = InstanceIdentifier.builder(
+ IntextIpMap.class).child(IpMapping.class, new IpMappingKey(routerId)).build();
+ return id;
+ }
+
+ protected InstanceIdentifier<IpPortMap> getIpPortMapIdentifier(long segid, String internal, NAPTEntryEvent.Protocol protocol) {
+ ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
+ InstanceIdentifier<IpPortMap> id = InstanceIdentifier.builder(
+ IntextIpPortMap.class).child(IpPortMapping.class, new IpPortMappingKey(segid)).child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType)).
+ child(IpPortMap.class, new IpPortMapKey(internal)).build();
+ return id;
+ }
+
+ protected SessionAddress checkIpPortMap(long segmentId, String internalIpPort, NAPTEntryEvent.Protocol protocol) {
+
+ LOG.debug("NAPT Service : checkIpPortMap called with segmentId {} and internalIpPort {}", segmentId, internalIpPort);
+ ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
+ // check if ip-port-map node is there
+ InstanceIdentifierBuilder<IntextIpProtocolType> idBuilder =
+ InstanceIdentifier.builder(IntextIpPortMap.class).child(IpPortMapping.class, new IpPortMappingKey(segmentId)).child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType));
+ InstanceIdentifier<IntextIpProtocolType> id = idBuilder.build();
+ Optional<IntextIpProtocolType> intextIpProtocolType = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
+ if (intextIpProtocolType.isPresent()) {
+ List<IpPortMap> ipPortMaps = intextIpProtocolType.get().getIpPortMap();
+ for (IpPortMap ipPortMap : ipPortMaps) {
+ if (ipPortMap.getIpPortInternal().equals(internalIpPort)) {
+ LOG.debug("NAPT Service : IpPortMap : {}", ipPortMap);
+ SessionAddress externalIpPort = new SessionAddress(ipPortMap.getIpPortExternal().getIpAddress(),
+ ipPortMap.getIpPortExternal().getPortNum());
+ LOG.debug("NAPT Service : checkIpPortMap returning successfully externalIP {} and port {}",
+ externalIpPort.getIpAddress(), externalIpPort.getPortNumber());
+ return externalIpPort;
+ }
+ }
+ }
+ // return null if not found
+ LOG.error("NAPT Service : no-entry in checkIpPortMap, returning NULL [should be OK] for segmentId {} and internalIPPort {}", segmentId, internalIpPort);
+ return null;
+ }
+
+ protected String checkIpMap(long segmentId, String internalIp) {
+
+ LOG.debug("NAPT Service : checkIpMap called with segmentId {} and internalIp {}", segmentId, internalIp);
+ String externalIp;
+ // check if ip-map node is there
+ InstanceIdentifierBuilder<IpMapping> idBuilder =
+ InstanceIdentifier.builder(IntextIpMap.class).child(IpMapping.class, new IpMappingKey(segmentId));
+ InstanceIdentifier<IpMapping> id = idBuilder.build();
+ Optional<IpMapping> ipMapping = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ if (ipMapping.isPresent()) {
+ List<IpMap> ipMaps = ipMapping.get().getIpMap();
+ for (IpMap ipMap : ipMaps) {
+ if (ipMap.getInternalIp().equals(internalIp)) {
+ LOG.debug("NAPT Service : IpMap : {}", ipMap);
+ externalIp = ipMap.getExternalIp().toString();
+ LOG.debug("NAPT Service : checkIpMap successfully returning externalIp {}", externalIp );
+ return externalIp;
+ } else if (ipMap.getInternalIp().contains("/")) { // subnet case
+ SubnetUtils subnetUtils = new SubnetUtils(ipMap.getInternalIp());
+ SubnetInfo subnetInfo = subnetUtils.getInfo();
+ if (subnetInfo.isInRange(internalIp)) {
+ LOG.debug("NAPT Service : internalIp {} found to be IpMap of internalIpSubnet {}", internalIp, ipMap.getInternalIp());
+ externalIp = ipMap.getExternalIp().toString();
+ LOG.debug("NAPT Service : checkIpMap successfully returning externalIp {}", externalIp );
+ return externalIp;
+ }
+ }
+ }
+ }
+ // return null if not found
+ LOG.error("NAPT Service : checkIpMap failed, returning NULL for segmentId {} and internalIp {}", segmentId, internalIp);
+ return null;
+ }
+
+ protected void removeSnatIntIpPortDS(long segmentId, SessionAddress address,NAPTEntryEvent.Protocol protocol) {
+ LOG.trace("NAPT Service : removeSnatIntIpPortDS method called for IntIpport {} of router {} ",address,segmentId);
+ ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
+ List<Integer> portList = NatUtil.getInternalIpPortListInfo(broker,segmentId,address.getIpAddress(),protocolType);
+ if (portList == null || portList.isEmpty() || !portList.contains(address.getPortNumber())) {
+ LOG.debug("Internal IP {} for port {} entry not found in SnatIntIpPort DS",address.getIpAddress(),address.getPortNumber());
+ return;
+ }
+ LOG.trace("NAPT Service : PortList {} retrieved for InternalIp {} of router {}",portList,address.getIpAddress(),segmentId);
+ Integer port = address.getPortNumber();
+ portList.remove(port);
+
+ IntIpProtoTypeBuilder builder = new IntIpProtoTypeBuilder();
+ IntIpProtoType intIpProtocolType = builder.setKey(new IntIpProtoTypeKey(protocolType)).setPorts(portList).build();
+ try {
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, NatUtil.buildSnatIntIpPortIdentifier(segmentId, address.getIpAddress(), protocolType), intIpProtocolType);
+ } catch (Exception ex) {
+ LOG.error("NAPT Service : Failed to write into snat-internal-ip-port-info with exception {}", ex.getMessage() );
+ }
+ LOG.debug("NAPT Service : Removing SnatIp {} Port {} of router {} from SNATIntIpport datastore : {}"
+ ,address.getIpAddress(),address.getPortNumber(),segmentId);
+ }
+
+ protected void removeFromSnatIpPortDS(long segmentId, String internalIp) {
+ InstanceIdentifier<IpPort> intIp = InstanceIdentifier.builder(SnatintIpPortMap.class).child
+ (IntipPortMap.class, new IntipPortMapKey(segmentId)).child(IpPort.class, new IpPortKey(internalIp)).build();
+ // remove from SnatIpPortDS
+ LOG.debug("NAPT Service : Removing SnatIpPort from datastore : {}", intIp);
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, intIp);
+
+ }
+
+ protected void removeFromIpPortMapDS(long segmentId, String internalIpPort, NAPTEntryEvent.Protocol protocol) {
+ ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
+ removeFromIpPortMapDS(segmentId, internalIpPort, protocolType);
+ }
+
+ protected void removeFromIpPortMapDS(long segmentId, String internalIpPort, ProtocolTypes protocolType) {
+ InstanceIdentifierBuilder<IpPortMap> idBuilder = InstanceIdentifier.builder(IntextIpPortMap.class)
+ .child(IpPortMapping.class, new IpPortMappingKey(segmentId)).child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
+ .child(IpPortMap.class, new IpPortMapKey(internalIpPort));
+ InstanceIdentifier<IpPortMap> id = idBuilder.build();
+ // remove from ipportmap DS
+ LOG.debug("NAPT Service : Removing ipportmap from datastore : {}", id);
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, id);
+ }
+
+ protected void removeFromIpMapDS(long segmentId, String internalIp) {
+ InstanceIdentifierBuilder<IpMap> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
+ .child(IpMapping.class, new IpMappingKey(segmentId))
+ .child(IpMap.class, new IpMapKey(internalIp));
+ InstanceIdentifier<IpMap> id = idBuilder.build();
+ // Get externalIp and decrement the counter
+ String externalIp = null;
+ Optional<IpMap> ipMap = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ if (ipMap.isPresent()) {
+ externalIp = ipMap.get().getExternalIp();
+ LOG.debug("NAT Service : externalIP is {}", externalIp);
+ }else{
+ LOG.warn("NAT Service : ipMap not present for the internal IP {}", internalIp);
+ }
+
+ if(externalIp!=null) {
+ updateCounter(segmentId, externalIp, false);
+ // remove from ipmap DS
+ LOG.debug("NAPT Service : Removing ipmap from datastore");
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id);
+ }else{
+ LOG.warn("NAT Service : externalIp not present for the internal IP {}", internalIp);
+ }
+ }
+
+ private void removeIpMappingForRouterID(long segmentId) {
+ InstanceIdentifierBuilder<IpMapping> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
+ .child(IpMapping.class, new IpMappingKey(segmentId));
+ InstanceIdentifier<IpMapping> id = idBuilder.build();
+ // Get all externalIps and decrement their counters before deleting the ipmap
+ String externalIp = null;
+ Optional<IpMapping> ipMapping = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ if (ipMapping.isPresent()) {
+ List<IpMap> ipMaps = ipMapping.get().getIpMap();
+ for (IpMap ipMap : ipMaps) {
+ externalIp = ipMap.getExternalIp();
+ LOG.debug("NAT Service : externalIP is {}", externalIp);
+ if(externalIp!=null) {
+ updateCounter(segmentId, externalIp, false);
+ }
+ }
+ }
+ // remove from ipmap DS
+ LOG.debug("NAPT Service : Removing Ipmap for router {} from datastore",segmentId);
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id);
+ }
+
+ void removeIpPortMappingForRouterID(long segmentId) {
+ InstanceIdentifier<IpPortMapping> idBuilder = InstanceIdentifier.builder(IntextIpPortMap.class)
+ .child(IpPortMapping.class, new IpPortMappingKey(segmentId)).build();
+ // remove from IntExtIpPortmap DS
+ LOG.debug("NAPT Service : Removing IntExtIpPort map for router {} from datastore",segmentId);
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, idBuilder);
+ }
+
+ void removeIntIpPortMappingForRouterID(long segmentId) {
+ InstanceIdentifier<IntipPortMap> intIp = InstanceIdentifier.builder(SnatintIpPortMap.class).child
+ (IntipPortMap.class, new IntipPortMapKey(segmentId)).build();
+ // remove from SnatIntIpPortmap DS
+ LOG.debug("NAPT Service : Removing SnatIntIpPort from datastore : {}", intIp);
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, intIp);
+ }
+
+ void removePortFromPool(String internalIpPort, String externalIp) {
+ LOG.debug("NAPT Service : removePortFromPool method called");
+ ReleaseIdInput idInput = new ReleaseIdInputBuilder().
+ setPoolName(externalIp)
+ .setIdKey(internalIpPort).build();
+ try {
+ Future<RpcResult<Void>> result = idManager.releaseId(idInput);
+ RpcResult<Void> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.error("NAPT Service : idmanager failed to remove port from pool {}", rpcResult.getErrors());
+ }
+ LOG.debug("NAPT Service : Removed port from pool for InternalIpPort {} with externalIp {}",internalIpPort,externalIp);
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("NAPT Service : idmanager failed with Exception {} when removing entry in pool with key {}, ", e, internalIpPort);
+ }
+ }
+
+ protected void initialiseExternalCounter(Routers routers, long routerId){
+ LOG.debug("NAPT Service : Initialise External IPs counter");
+ List<String> externalIps = routers.getExternalIps();
+
+ //update the new counter value for this externalIp
+ for(String externalIp : externalIps) {
+ String[] IpSplit = externalIp.split("/");
+ String extIp = IpSplit[0];
+ String extPrefix = Short.toString(NatConstants.DEFAULT_PREFIX);
+ if(IpSplit.length==2) {
+ extPrefix = IpSplit[1];
+ }
+ extIp = extIp + "/" + extPrefix;
+ initialiseNewExternalIpCounter(routerId, extIp);
+ }
+ }
+
+ protected void initialiseNewExternalIpCounter(long routerId, String ExternalIp){
+ ExternalIpCounter externalIpCounterData = new ExternalIpCounterBuilder().setKey(new ExternalIpCounterKey(ExternalIp)).
+ setExternalIp(ExternalIp).setCounter((short) 0).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, getExternalIpsIdentifier(routerId, ExternalIp), externalIpCounterData);
+ }
+
+ protected void removeExternalCounter(long routerId){
+ // Remove from external-counters model
+ InstanceIdentifier<ExternalCounters> id = InstanceIdentifier.builder(ExternalIpsCounter.class).child(ExternalCounters.class, new ExternalCountersKey(routerId)).build();
+ LOG.debug("NAPT Service : Removing ExternalCounterd from datastore");
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id);
+ }
+
+ protected void removeExternalIpCounter(long routerId, String externalIp){
+ // Remove from external-counters model
+ InstanceIdentifier<ExternalIpCounter> id = InstanceIdentifier.builder(ExternalIpsCounter.class).child(ExternalCounters.class,
+ new ExternalCountersKey(routerId)).child(ExternalIpCounter.class, new ExternalIpCounterKey(externalIp)).build();
+ LOG.debug("NAPT Service : Removing ExternalIpsCounter from datastore");
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, id);
+ }
+
+}
\ 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.natservice.internal;
+
+import org.opendaylight.controller.liblldp.NetUtils;
+import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
+import org.opendaylight.vpnservice.mdsalutil.packet.Ethernet;
+import org.opendaylight.vpnservice.mdsalutil.packet.IPv4;
+import org.opendaylight.vpnservice.mdsalutil.packet.TCP;
+import org.opendaylight.vpnservice.mdsalutil.packet.UDP;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.HashSet;
+import com.google.common.primitives.Ints;
+
+public class NaptPacketInHandler implements PacketProcessingListener {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NaptPacketInHandler.class);
+ private final static HashSet<String> incomingPacketMap = new HashSet<>();
+ private final EventDispatcher naptEventdispatcher;
+
+ public NaptPacketInHandler(EventDispatcher eventDispatcher) {
+ this.naptEventdispatcher = eventDispatcher;
+ }
+
+ @Override
+ public void onPacketReceived(PacketReceived packetReceived) {
+ String internalIPAddress = "";
+ int portNumber = 0;
+ long routerId = 0L;
+ NAPTEntryEvent.Operation operation = NAPTEntryEvent.Operation.ADD;
+ NAPTEntryEvent.Protocol protocol;
+
+ Short tableId = packetReceived.getTableId().getValue();
+
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("packet: {}, tableId {}", packetReceived, tableId);
+ }
+
+ if (tableId == NatConstants.OUTBOUND_NAPT_TABLE) {
+ LOG.debug("NAT Service : NAPTPacketInHandler Packet for Outbound NAPT Table");
+ byte[] inPayload = packetReceived.getPayload();
+ Ethernet ethPkt = new Ethernet();
+ if (inPayload != null) {
+ try {
+ ethPkt.deserialize(inPayload, 0, inPayload.length * NetUtils.NumBitsInAByte);
+ } catch (Exception e) {
+ LOG.warn("Failed to decode Packet", e);
+ return;
+ }
+ if (ethPkt.getPayload() instanceof IPv4) {
+ IPv4 ipPkt = (IPv4) ethPkt.getPayload();
+ byte[] ipSrc = Ints.toByteArray(ipPkt.getSourceAddress());
+
+ internalIPAddress = NatUtil.toStringIpAddress(ipSrc, LOG);
+ LOG.trace("Retrieved internalIPAddress {}", internalIPAddress);
+ if (ipPkt.getPayload() instanceof TCP) {
+ TCP tcpPkt = (TCP) ipPkt.getPayload();
+ portNumber = tcpPkt.getSourcePort();
+ if(portNumber < 0){
+ portNumber = 32767 + portNumber + 32767 + 2;
+ LOG.trace("Retrieved and extracted TCP portNumber {}", portNumber);
+ }
+ protocol = NAPTEntryEvent.Protocol.TCP;
+ LOG.trace("Retrieved TCP portNumber {}", portNumber);
+ } else if (ipPkt.getPayload() instanceof UDP) {
+ UDP udpPkt = (UDP) ipPkt.getPayload();
+ portNumber = udpPkt.getSourcePort();
+ if(portNumber < 0){
+ portNumber = 32767 + portNumber + 32767 + 2;
+ LOG.trace("Retrieved and extracted UDP portNumber {}", portNumber);
+ }
+ protocol = NAPTEntryEvent.Protocol.UDP;
+ LOG.trace("Retrieved UDP portNumber {}", portNumber);
+ } else {
+ LOG.error("Incoming Packet is neither TCP or UDP packet");
+ return;
+ }
+ } else {
+ LOG.error("Incoming Packet is not IPv4 packet");
+ return;
+ }
+
+ if(internalIPAddress != null) {
+ String sourceIPPortKey = internalIPAddress + ":" + portNumber;
+ LOG.debug("NAT Service : sourceIPPortKey {} mapping maintained in the map", sourceIPPortKey);
+ if (!incomingPacketMap.contains(sourceIPPortKey)) {
+ incomingPacketMap.add(internalIPAddress + portNumber);
+
+ BigInteger metadata = packetReceived.getMatch().getMetadata().getMetadata();
+ routerId = (metadata.and(MetaDataUtil.METADATA_MASK_VRFID)).longValue();
+ if( routerId <= 0) {
+ LOG.error("Nat Service : Router ID is invalid");
+ return;
+ }
+ //send to Event Queue
+ NAPTEntryEvent naptEntryEvent = new NAPTEntryEvent(internalIPAddress,portNumber,routerId,
+ operation,protocol);
+ naptEventdispatcher.addNaptEvent(naptEntryEvent);
+ } else {
+ LOG.trace("Ignore the packet, already processed");
+ }
+ }else {
+ LOG.error("Nullpointer exception in retrieving internalIPAddress");
+ }
+ }
+ }else {
+ LOG.trace("Packet is not from the Outbound NAPT table");
+ }
+ }
+
+ public void removeIncomingPacketMap(String sourceIPPortKey) {
+ incomingPacketMap.remove(sourceIPPortKey);
+ LOG.debug("NAT Service : sourceIPPortKey {} mapping is removed from map", sourceIPPortKey);
+ }
+}
\ 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.natservice.internal;
+
+import com.google.common.base.Optional;
+import org.opendaylight.bgpmanager.api.IBgpManager;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+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.Uuid;
+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.group.types.rev131018.GroupTypes;
+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.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.FibRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeGre;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.TunnelTypeVxlan;
+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.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.GetTunnelInterfaceNameOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ext.routers.Routers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ext.routers.RoutersKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMappingKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.IpPortMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.ip.port.map.IpPortExternal;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.VpnRpcService;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class NaptSwitchHA {
+ private static final Logger LOG = LoggerFactory.getLogger(NaptSwitchHA.class);
+ private final DataBroker dataBroker;
+ private IMdsalApiManager mdsalManager;
+ private ItmRpcService itmManager;
+ private OdlInterfaceRpcService interfaceManager;
+ private IdManagerService idManager;
+ private NAPTSwitchSelector naptSwitchSelector;
+ private ExternalRoutersListener externalRouterListener;
+ private IBgpManager bgpManager;
+ private VpnRpcService vpnService;
+ private FibRpcService fibService;
+
+ public NaptSwitchHA(DataBroker broker,NAPTSwitchSelector selector){
+ dataBroker = broker;
+ naptSwitchSelector = selector;
+ }
+
+ public void setItmManager(ItmRpcService itmManager) {
+ this.itmManager = itmManager;
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
+ this.interfaceManager = interfaceManager;
+ }
+
+ public void setIdManager(IdManagerService idManager) {
+ this.idManager = idManager;
+ }
+
+ void setExternalRoutersListener(ExternalRoutersListener externalRoutersListener) {
+ this.externalRouterListener = externalRoutersListener;
+ }
+
+ public void setBgpManager(IBgpManager bgpManager) {
+ this.bgpManager = bgpManager;
+ }
+
+ public void setVpnService(VpnRpcService vpnService) {
+ this.vpnService = vpnService;
+ }
+
+ public void setFibService(FibRpcService fibService) {
+ this.fibService = fibService;
+ }
+
+ /* This method checks the switch that gone down is a NaptSwitch for a router.
+ If it is a NaptSwitch
+ 1) selects new NAPT switch
+ 2) installs nat flows in new NAPT switch
+ table 21(FIB)->26(PSNAT)->group(resubmit/napttunnel)->36(Terminating)->46(outbound)->47(resubmit)->21
+ 3) modify the group and miss entry flow in other vSwitches pointing to newNaptSwitch
+ 4) Remove nat flows in oldNaptSwitch
+ */
+ /*public void handleNaptSwitchDown(BigInteger dpnId){
+
+ LOG.debug("handleNaptSwitchDown method is called with dpnId {}",dpnId);
+ BigInteger naptSwitch;
+ try {
+ NaptSwitches naptSwitches = NatUtil.getNaptSwitch(dataBroker);
+ if (naptSwitches == null || naptSwitches.getRouterToNaptSwitch() == null || naptSwitches.getRouterToNaptSwitch().isEmpty()) {
+ LOG.debug("NaptSwitchDown: NaptSwitch is not allocated for none of the routers");
+ return;
+ }
+ for (RouterToNaptSwitch routerToNaptSwitch : naptSwitches.getRouterToNaptSwitch()) {
+ String routerName = routerToNaptSwitch.getRouterName();
+ naptSwitch = routerToNaptSwitch.getPrimarySwitchId();
+ boolean naptStatus = isNaptSwitchDown(routerName,dpnId,naptSwitch);
+ if (!naptStatus) {
+ LOG.debug("NaptSwitchDown: Switch with DpnId {} is not naptSwitch for router {}",
+ dpnId, routerName);
+ } else {
+ removeSnatFlowsInOldNaptSwitch(routerName,naptSwitch);
+ return;
+ }
+ }
+ } catch (Exception ex) {
+ LOG.error("Exception in handleNaptSwitchDown method {}",ex);
+ }
+ }*/
+
+ protected void removeSnatFlowsInOldNaptSwitch(String routerName, BigInteger naptSwitch) {
+ //remove SNAT flows in old NAPT SWITCH
+ Long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ if (routerId == NatConstants.INVALID_ID) {
+ LOG.error("Invalid routerId returned for routerName {}",routerName);
+ return;
+ }
+
+ //Remove the Terminating Service table entry which forwards the packet to Outbound NAPT Table
+ String tsFlowRef = externalRouterListener.getFlowRefTs(naptSwitch, NatConstants.TERMINATING_SERVICE_TABLE, routerId);
+ FlowEntity tsNatFlowEntity = NatUtil.buildFlowEntity(naptSwitch, NatConstants.TERMINATING_SERVICE_TABLE, tsFlowRef);
+
+ LOG.info("Remove the flow in table {} for the old napt switch with the DPN ID {} and router ID {}"
+ ,NatConstants.TERMINATING_SERVICE_TABLE, naptSwitch, routerId);
+ mdsalManager.removeFlow(tsNatFlowEntity);
+
+ //Remove the Outbound flow entry which forwards the packet to Outbound NAPT Table
+ String outboundNatFlowRef = externalRouterListener.getFlowRefOutbound(naptSwitch, NatConstants.OUTBOUND_NAPT_TABLE, routerId);
+ FlowEntity outboundNatFlowEntity = NatUtil.buildFlowEntity(naptSwitch,
+ NatConstants.OUTBOUND_NAPT_TABLE, outboundNatFlowRef);
+ LOG.info("Remove the flow in table {} for the old napt switch with the DPN ID {} and router ID {}"
+ ,NatConstants.OUTBOUND_NAPT_TABLE, naptSwitch, routerId);
+ mdsalManager.removeFlow(outboundNatFlowEntity);
+
+ //Remove the NAPT_PFIB_TABLE(47) flow entry forwards the packet to Fib Table for inbound traffic matching on the router ID.
+ String naptPFibflowRef = externalRouterListener.getFlowRefTs(naptSwitch, NatConstants.NAPT_PFIB_TABLE, routerId);
+ FlowEntity naptPFibFlowEntity = NatUtil.buildFlowEntity(naptSwitch, NatConstants.NAPT_PFIB_TABLE,naptPFibflowRef);
+ LOG.info("Remove the flow in table {} for the old napt switch with the DPN ID {} and router ID {}",
+ NatConstants.NAPT_PFIB_TABLE, naptSwitch, routerId);
+ mdsalManager.removeFlow(naptPFibFlowEntity);
+
+ //Remove the NAPT_PFIB_TABLE(47) flow entry forwards the packet to Fib Table for outbound traffic matching on the vpn ID.
+ Long vpnId = getVpnIdForRouter(routerId);
+ if (vpnId != NatConstants.INVALID_ID) {
+ String naptFibflowRef = externalRouterListener.getFlowRefTs(naptSwitch, NatConstants.NAPT_PFIB_TABLE, vpnId);
+ FlowEntity naptFibFlowEntity = NatUtil.buildFlowEntity(naptSwitch, NatConstants.NAPT_PFIB_TABLE,naptFibflowRef);
+ LOG.info("Remove the flow in table {} for the old napt switch with the DPN ID {} and vpnId {}",
+ NatConstants.NAPT_PFIB_TABLE, naptSwitch, vpnId);
+ mdsalManager.removeFlow(naptFibFlowEntity);
+ } else {
+ LOG.error("Invalid vpnId retrieved for routerId {}",routerId);
+ return;
+ }
+
+ //Remove Fib entries and 36-> 44
+ Uuid networkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
+ if (networkId != null) {
+ List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker, routerId);
+ if (externalIps != null) {
+ externalRouterListener.clrRtsFromBgpAndDelFibTs(naptSwitch, routerId, networkId, externalIps, null);
+ LOG.debug("Successfully removed fib entries in old naptswitch {} for router {} with networkId {} and externalIps {}",
+ naptSwitch,routerId,networkId,externalIps);
+ } else {
+ LOG.debug("ExternalIps not found for router {} with networkId {}", routerName, networkId);
+ }
+ } else {
+ LOG.debug("network not associated to router {}", routerId);
+ }
+
+ //For the router ID get the internal IP , internal port and the corresponding external IP and external Port.
+ IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker, routerId);
+ if (ipPortMapping == null || ipPortMapping.getIntextIpProtocolType() == null || ipPortMapping.getIntextIpProtocolType().isEmpty()) {
+ LOG.debug("No Internal Ip Port mapping associated to router {}, no flows need to be removed in" +
+ "oldNaptSwitch {}", routerId, naptSwitch);
+ return;
+ }
+ BigInteger cookieSnatFlow = NatUtil.getCookieNaptFlow(routerId);
+ List<IntextIpProtocolType> intextIpProtocolTypes = ipPortMapping.getIntextIpProtocolType();
+ for(IntextIpProtocolType intextIpProtocolType : intextIpProtocolTypes) {
+ if (intextIpProtocolType.getIpPortMap() == null || intextIpProtocolType.getIpPortMap().isEmpty()) {
+ LOG.debug("No {} session associated to router {},no flows need to be removed in oldNaptSwitch {}",
+ intextIpProtocolType.getProtocol(),routerId,naptSwitch);
+ break;
+ }
+ List<IpPortMap> ipPortMaps = intextIpProtocolType.getIpPortMap();
+ for(IpPortMap ipPortMap : ipPortMaps) {
+ String ipPortInternal = ipPortMap.getIpPortInternal();
+ String[] ipPortParts = ipPortInternal.split(":");
+ if(ipPortParts.length != 2) {
+ LOG.error("Unable to retrieve the Internal IP and port");
+ continue;
+ }
+ String internalIp = ipPortParts[0];
+ String internalPort = ipPortParts[1];
+
+ //Build and remove flow in outbound NAPT table
+ String switchFlowRef = NatUtil.getNaptFlowRef(naptSwitch, NatConstants.OUTBOUND_NAPT_TABLE, String.valueOf(routerId),
+ internalIp, Integer.valueOf(internalPort));
+ FlowEntity outboundNaptFlowEntity = NatUtil.buildFlowEntity(naptSwitch, NatConstants.OUTBOUND_NAPT_TABLE,
+ cookieSnatFlow, switchFlowRef);
+
+ LOG.info("Remove the flow in table {} for old napt switch with the DPN ID {} and router ID {}",
+ NatConstants.OUTBOUND_NAPT_TABLE,naptSwitch, routerId);
+ mdsalManager.removeFlow(outboundNaptFlowEntity);
+
+ IpPortExternal ipPortExternal = ipPortMap.getIpPortExternal();
+ if (ipPortExternal == null) {
+ LOG.debug("External Ipport mapping not found for internalIp {} with port {} for router", internalIp,
+ internalPort, routerId);
+ continue;
+ }
+ String externalIp = ipPortExternal.getIpAddress();
+ int externalPort = ipPortExternal.getPortNum();
+
+ //Build and remove flow in inbound NAPT table
+ switchFlowRef = NatUtil.getNaptFlowRef(naptSwitch, NatConstants.INBOUND_NAPT_TABLE, String.valueOf(routerId),
+ externalIp, externalPort);
+ FlowEntity inboundNaptFlowEntity = NatUtil.buildFlowEntity(naptSwitch, NatConstants.INBOUND_NAPT_TABLE,
+ cookieSnatFlow, switchFlowRef);
+
+ LOG.info("Remove the flow in table {} for old napt switch with the DPN ID {} and router ID {}",
+ NatConstants.INBOUND_NAPT_TABLE,naptSwitch, routerId);
+ mdsalManager.removeFlow(inboundNaptFlowEntity);
+ }
+ }
+
+ }
+
+ /*public boolean isNaptSwitchDown(String routerName, BigInteger dpnId , BigInteger naptSwitch) {
+ if (!naptSwitch.equals(dpnId)) {
+ LOG.debug("DpnId {} is not a naptSwitch {} for Router {}",dpnId, naptSwitch, routerName);
+ return false;
+ }
+ LOG.debug("NaptSwitch {} is down for Router {}", naptSwitch, routerName);
+ //elect a new NaptSwitch
+ naptSwitch = naptSwitchSelector.selectNewNAPTSwitch(routerName);
+ if (naptSwitch.equals(BigInteger.ZERO)) {
+ LOG.info("No napt switch is elected since all the switches for router {} are down",routerName);
+ boolean naptUpdatedStatus = updateNaptSwitch(routerName,naptSwitch);
+ if(!naptUpdatedStatus) {
+ LOG.debug("Failed to update naptSwitch {} for router {} in ds", naptSwitch,routerName);
+ }
+ return true;
+ }
+ //checking elected switch health status
+ if (!getSwitchStatus(naptSwitch)) {
+ LOG.error("Newly elected Napt switch {} for router {} is down", naptSwitch, routerName);
+ return true;
+ }
+ LOG.debug("New NaptSwitch {} is up for Router {} and can proceed for flow installation",naptSwitch, routerName);
+ Long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ if (routerId == NatConstants.INVALID_ID) {
+ LOG.error("Invalid routerId returned for routerName {}", routerName);
+ return true;
+ }
+ //update napt model for new napt switch
+ boolean naptUpdated = updateNaptSwitch(routerName, naptSwitch);
+ if (naptUpdated) {
+ //update group of naptswitch point to table36/ordinary switch point to naptswitchtunnelport
+ updateNaptSwitchBucketStatus(routerName, naptSwitch);
+ } else {
+ LOG.error("Failed to update naptSwitch model for newNaptSwitch {} for router {}",naptSwitch, routerName);
+ }
+
+ installSnatFlows(routerName,routerId,naptSwitch);
+
+ boolean flowInstalledStatus = handleNatFlowsInNewNaptSwitch(routerId, dpnId, naptSwitch);
+ if (flowInstalledStatus) {
+ LOG.debug("Installed all active session flows in newNaptSwitch {} for routerName {}", naptSwitch, routerName);
+ } else {
+ LOG.error("Failed to install flows in newNaptSwitch {} for routerId {}", naptSwitch, routerId);
+ }
+ return true;
+ }*/
+
+ public boolean isNaptSwitchDown(String routerName, BigInteger dpnId , BigInteger naptSwitch,Long routerVpnId) {
+ if (!naptSwitch.equals(dpnId)) {
+ LOG.debug("DpnId {} is not a naptSwitch {} for Router {}",dpnId, naptSwitch, routerName);
+ return false;
+ }
+ LOG.debug("NaptSwitch {} is down for Router {}", naptSwitch, routerName);
+ //elect a new NaptSwitch
+ naptSwitch = naptSwitchSelector.selectNewNAPTSwitch(routerName);
+ if (naptSwitch.equals(BigInteger.ZERO)) {
+ LOG.info("No napt switch is elected since all the switches for router {} are down",routerName);
+ boolean naptUpdatedStatus = updateNaptSwitch(routerName,naptSwitch);
+ if(!naptUpdatedStatus) {
+ LOG.debug("Failed to update naptSwitch {} for router {} in ds", naptSwitch,routerName);
+ }
+ return true;
+ }
+ //checking elected switch health status
+ if (!getSwitchStatus(naptSwitch)) {
+ LOG.error("Newly elected Napt switch {} for router {} is down", naptSwitch, routerName);
+ return true;
+ }
+ LOG.debug("New NaptSwitch {} is up for Router {} and can proceed for flow installation",naptSwitch, routerName);
+ Long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ if (routerId == NatConstants.INVALID_ID) {
+ LOG.error("Invalid routerId returned for routerName {}", routerName);
+ return true;
+ }
+ //update napt model for new napt switch
+ boolean naptUpdated = updateNaptSwitch(routerName, naptSwitch);
+ if (naptUpdated) {
+ //update group of naptswitch point to table36/ordinary switch point to naptswitchtunnelport
+ updateNaptSwitchBucketStatus(routerName, naptSwitch);
+ } else {
+ LOG.error("Failed to update naptSwitch model for newNaptSwitch {} for router {}",naptSwitch, routerName);
+ }
+
+ installSnatFlows(routerName,routerId,naptSwitch,routerVpnId);
+
+ boolean flowInstalledStatus = handleNatFlowsInNewNaptSwitch(routerId, dpnId, naptSwitch,routerVpnId);
+ if (flowInstalledStatus) {
+ LOG.debug("Installed all active session flows in newNaptSwitch {} for routerName {}", naptSwitch, routerName);
+ } else {
+ LOG.error("Failed to install flows in newNaptSwitch {} for routerId {}", naptSwitch, routerId);
+ }
+ return true;
+ }
+
+ private String getExtNetworkVpnName(long routerId) {
+ Uuid networkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
+ if(networkId == null) {
+ LOG.error("networkId is null for the router ID {}", routerId);
+ } else {
+ final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
+ if (vpnName != null) {
+ LOG.debug("retrieved vpn name {} associated with ext nw {} in router {}",
+ vpnName,networkId,routerId);
+ return vpnName;
+ } else {
+ LOG.error("No VPN associated with ext nw {} belonging to routerId {}",
+ networkId, routerId);
+ }
+ }
+ return null;
+ }
+
+ public void updateNaptSwitchBucketStatus(String routerName, BigInteger naptSwitch) {
+ LOG.debug("updateNaptSwitchBucketStatus method is called");
+
+ List<BigInteger> dpnList = naptSwitchSelector.getDpnsForVpn(routerName);
+ //List<BigInteger> dpnList = getDpnListForRouter(routerName);
+ for (BigInteger dpn : dpnList) {
+ if (dpn.equals(naptSwitch)) {
+ LOG.debug("Updating SNAT_TABLE missentry for DpnId {} which is naptSwitch for router {}",dpn,routerName);
+ List<BucketInfo> bucketInfoList = handleGroupInPrimarySwitch();
+ modifySnatGroupEntry(naptSwitch, bucketInfoList, routerName);
+ } else {
+ LOG.debug("Updating SNAT_TABLE missentry for DpnId {} which is not naptSwitch for router {}",dpn,routerName);
+ List<BucketInfo> bucketInfoList = handleGroupInNeighborSwitches(dpn, routerName, naptSwitch);
+ if (bucketInfoList == null) {
+ LOG.debug("Failed to populate bucketInfo for orinaryswitch {} whose naptSwitch {} for router {} ",
+ dpn,naptSwitch,routerName);
+ return;
+ }
+ modifySnatGroupEntry(naptSwitch, bucketInfoList, routerName);
+ }
+ }
+ }
+
+ /*private boolean handleNatFlowsInNewNaptSwitch(Long routerId,BigInteger oldNaptSwitch, BigInteger newNaptSwitch) {
+
+ LOG.debug("Proceeding to install flows in newNaptSwitch {} for routerId {}", newNaptSwitch,routerId);
+ IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker,routerId);
+ if (ipPortMapping == null || ipPortMapping.getIntextIpProtocolType() == null || ipPortMapping.getIntextIpProtocolType().isEmpty()) {
+ LOG.debug("No Internal Ip Port mapping associated to router {}, no flows need to be installed in" +
+ "newNaptSwitch {}", routerId, newNaptSwitch);
+ return true;
+ }
+ //getvpnId
+ Long vpnId = getVpnIdForRouter(routerId);
+ if (vpnId == NatConstants.INVALID_ID) {
+ LOG.error("Invalid vpnId for routerId {}",routerId);
+ return false;
+ }
+ Long bgpVpnId = NatConstants.INVALID_ID;
+ for (IntextIpProtocolType protocolType : ipPortMapping.getIntextIpProtocolType()) {
+ if (protocolType.getIpPortMap() == null || protocolType.getIpPortMap().isEmpty()) {
+ LOG.debug("No {} session associated to router {}", protocolType.getProtocol(), routerId);
+ return true;
+ }
+ for (IpPortMap intIpPortMap : protocolType.getIpPortMap()) {
+ String internalIpAddress = intIpPortMap.getIpPortInternal().split(":")[0];
+ String intportnum = intIpPortMap.getIpPortInternal().split(":")[1];
+
+ //Get the external IP address and the port from the model
+ NAPTEntryEvent.Protocol proto = protocolType.getProtocol().toString().equals(ProtocolTypes.TCP.toString())
+ ? NAPTEntryEvent.Protocol.TCP : NAPTEntryEvent.Protocol.UDP;
+ IpPortExternal ipPortExternal = NatUtil.getExternalIpPortMap(dataBroker, routerId,
+ internalIpAddress, intportnum, proto);
+ if (ipPortExternal == null) {
+ LOG.debug("External Ipport mapping is not found for internalIp {} with port {}", internalIpAddress, intportnum);
+ continue;
+ }
+ String externalIpAddress = ipPortExternal.getIpAddress();
+ Integer extportNumber = ipPortExternal.getPortNum();
+ LOG.debug("ExternalIPport {}:{} mapping for internal ipport {}:{}",externalIpAddress,extportNumber,
+ internalIpAddress,intportnum);
+
+ SessionAddress sourceAddress = new SessionAddress(internalIpAddress,Integer.valueOf(intportnum));
+ SessionAddress externalAddress = new SessionAddress(externalIpAddress,extportNumber);
+
+ //checking naptSwitch status before installing flows
+ if(getSwitchStatus(newNaptSwitch)) {
+ //Install the flow in newNaptSwitch Outbound NAPT table.
+ try {
+ NaptEventHandler.buildAndInstallNatFlows(newNaptSwitch, NatConstants.OUTBOUND_NAPT_TABLE,
+ vpnId, routerId, bgpVpnId ,sourceAddress, externalAddress, proto);
+ } catch (Exception ex) {
+ LOG.error("Failed to add flow in OUTBOUND_NAPT_TABLE for routerid {} dpnId {} ipport {}:{} proto {}" +
+ "extIpport {}:{}", routerId, newNaptSwitch, internalIpAddress
+ , intportnum, proto, externalAddress, extportNumber);
+ return false;
+ }
+ LOG.debug("Succesfully installed a flow in SecondarySwitch {} Outbound NAPT table for router {} " +
+ "ipport {}:{} proto {} extIpport {}:{}", newNaptSwitch,routerId, internalIpAddress
+ , intportnum, proto, externalAddress, extportNumber);
+ //Install the flow in newNaptSwitch Inbound NAPT table.
+ try {
+ NaptEventHandler.buildAndInstallNatFlows(newNaptSwitch, NatConstants.INBOUND_NAPT_TABLE,
+ vpnId, routerId, bgpVpnId,externalAddress, sourceAddress, proto);
+ } catch (Exception ex) {
+ LOG.error("Failed to add flow in INBOUND_NAPT_TABLE for routerid {} dpnId {} extIpport{}:{} proto {} ipport {}:{}",
+ routerId, newNaptSwitch, externalAddress, extportNumber,
+ proto, internalIpAddress, intportnum);
+ return false;
+ }
+ LOG.debug("Succesfully installed a flow in SecondarySwitch {} Inbound NAPT table for router {} " +
+ "ipport {}:{} proto {} extIpport {}:{}", newNaptSwitch,routerId, internalIpAddress
+ , intportnum, proto, externalAddress, extportNumber);
+
+ } else {
+ LOG.error("NewNaptSwitch {} gone down while installing flows from oldNaptswitch {}",
+ newNaptSwitch,oldNaptSwitch);
+ return false;
+ }
+ }
+ }
+ return true;
+ }*/
+
+ private boolean handleNatFlowsInNewNaptSwitch(Long routerId,BigInteger oldNaptSwitch, BigInteger newNaptSwitch,Long routerVpnId) {
+
+ LOG.debug("Proceeding to install flows in newNaptSwitch {} for routerId {}", newNaptSwitch,routerId);
+ IpPortMapping ipPortMapping = NatUtil.getIportMapping(dataBroker,routerId);
+ if (ipPortMapping == null || ipPortMapping.getIntextIpProtocolType() == null || ipPortMapping.getIntextIpProtocolType().isEmpty()) {
+ LOG.debug("No Internal Ip Port mapping associated to router {}, no flows need to be installed in" +
+ "newNaptSwitch {}", routerId, newNaptSwitch);
+ return true;
+ }
+ //getvpnId
+ Long vpnId = getVpnIdForRouter(routerId);
+ if (vpnId == NatConstants.INVALID_ID) {
+ LOG.error("Invalid vpnId for routerId {}",routerId);
+ return false;
+ }
+ Long bgpVpnId;
+ if(routerId.equals(routerVpnId)) {
+ bgpVpnId = NatConstants.INVALID_ID;
+ } else {
+ bgpVpnId = routerVpnId;
+ }
+ LOG.debug("retrieved bgpVpnId {} for router {}",bgpVpnId,routerId);
+ for (IntextIpProtocolType protocolType : ipPortMapping.getIntextIpProtocolType()) {
+ if (protocolType.getIpPortMap() == null || protocolType.getIpPortMap().isEmpty()) {
+ LOG.debug("No {} session associated to router {}", protocolType.getProtocol(), routerId);
+ return true;
+ }
+ for (IpPortMap intIpPortMap : protocolType.getIpPortMap()) {
+ String internalIpAddress = intIpPortMap.getIpPortInternal().split(":")[0];
+ String intportnum = intIpPortMap.getIpPortInternal().split(":")[1];
+
+ //Get the external IP address and the port from the model
+ NAPTEntryEvent.Protocol proto = protocolType.getProtocol().toString().equals(ProtocolTypes.TCP.toString())
+ ? NAPTEntryEvent.Protocol.TCP : NAPTEntryEvent.Protocol.UDP;
+ IpPortExternal ipPortExternal = NatUtil.getExternalIpPortMap(dataBroker, routerId,
+ internalIpAddress, intportnum, proto);
+ if (ipPortExternal == null) {
+ LOG.debug("External Ipport mapping is not found for internalIp {} with port {}", internalIpAddress, intportnum);
+ continue;
+ }
+ String externalIpAddress = ipPortExternal.getIpAddress();
+ Integer extportNumber = ipPortExternal.getPortNum();
+ LOG.debug("ExternalIPport {}:{} mapping for internal ipport {}:{}",externalIpAddress,extportNumber,
+ internalIpAddress,intportnum);
+
+ SessionAddress sourceAddress = new SessionAddress(internalIpAddress,Integer.valueOf(intportnum));
+ SessionAddress externalAddress = new SessionAddress(externalIpAddress,extportNumber);
+
+ //checking naptSwitch status before installing flows
+ if(getSwitchStatus(newNaptSwitch)) {
+ //Install the flow in newNaptSwitch Outbound NAPT table.
+ try {
+ NaptEventHandler.buildAndInstallNatFlows(newNaptSwitch, NatConstants.OUTBOUND_NAPT_TABLE,
+ vpnId, routerId, bgpVpnId, sourceAddress, externalAddress, proto);
+ } catch (Exception ex) {
+ LOG.error("Failed to add flow in OUTBOUND_NAPT_TABLE for routerid {} dpnId {} ipport {}:{} proto {}" +
+ "extIpport {}:{} BgpVpnId {} - {}", routerId, newNaptSwitch, internalIpAddress
+ , intportnum, proto, externalAddress, extportNumber,bgpVpnId,ex);
+ return false;
+ }
+ LOG.debug("Successfully installed a flow in SecondarySwitch {} Outbound NAPT table for router {} " +
+ "ipport {}:{} proto {} extIpport {}:{} BgpVpnId {}", newNaptSwitch,routerId, internalIpAddress
+ , intportnum, proto, externalAddress, extportNumber,bgpVpnId);
+ //Install the flow in newNaptSwitch Inbound NAPT table.
+ try {
+ NaptEventHandler.buildAndInstallNatFlows(newNaptSwitch, NatConstants.INBOUND_NAPT_TABLE,
+ vpnId, routerId, bgpVpnId, externalAddress, sourceAddress, proto);
+ } catch (Exception ex) {
+ LOG.error("Failed to add flow in INBOUND_NAPT_TABLE for routerid {} dpnId {} extIpport{}:{} proto {} " +
+ "ipport {}:{} BgpVpnId {}", routerId, newNaptSwitch, externalAddress, extportNumber, proto,
+ internalIpAddress, intportnum,bgpVpnId);
+ return false;
+ }
+ LOG.debug("Successfully installed a flow in SecondarySwitch {} Inbound NAPT table for router {} " +
+ "ipport {}:{} proto {} extIpport {}:{} BgpVpnId {}", newNaptSwitch,routerId, internalIpAddress
+ , intportnum, proto, externalAddress, extportNumber,bgpVpnId);
+
+ } else {
+ LOG.error("NewNaptSwitch {} gone down while installing flows from oldNaptswitch {}",
+ newNaptSwitch,oldNaptSwitch);
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private Long getVpnIdForRouter(Long routerId) {
+ try {
+ //getvpnId
+ Uuid networkId = NatUtil.getNetworkIdFromRouterId(dataBroker, routerId);
+ if (networkId == null) {
+ LOG.debug("network is not associated to router {}", routerId);
+ } else {
+ Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
+ if (vpnUuid == null) {
+ LOG.debug("vpn is not associated for network {} in router {}", networkId, routerId);
+ } else {
+ Long vpnId = NatUtil.getVpnId(dataBroker, vpnUuid.getValue());
+ if (vpnId > 0) {
+ LOG.debug("retrieved vpnId {} for router {}",vpnId,routerId);
+ return vpnId;
+ } else {
+ LOG.debug("retrieved invalid vpn Id");
+ }
+ }
+ }
+ } catch (Exception ex){
+ LOG.debug("Exception while retrieving vpnId for router {} - {}", routerId, ex);
+ }
+ return NatConstants.INVALID_ID;
+ }
+
+/*
+ private List<BigInteger> getDpnListForRouter(String routerName) {
+ long bgpVpnId = NatUtil.getBgpVpnId(dataBroker, routerName);
+ if (bgpVpnId != NatConstants.INVALID_ID) {
+ return NatUtil.getDpnsForRouter(dataBroker, routerName);
+ }
+ List<BigInteger> dpnList = new ArrayList<BigInteger>();
+ List<VpnToDpnList> vpnDpnList = NatUtil.getVpnToDpnList(dataBroker, routerName);
+ if (vpnDpnList == null || vpnDpnList.isEmpty()) {
+ LOG.debug("NAT Service : Unable to get the switches for the router {} from the VPNInstanceOpData", routerName);
+ dpnList = NatUtil.getDpnsForRouter(dataBroker, routerName);
+ if(dpnList == null || dpnList.isEmpty()){
+ LOG.debug("NAT Service : No switches are part of router {}", routerName);
+ LOG.error("NAT Service : NAPT SWITCH SELECTION STOPPED DUE TO NO DPNS SCENARIO FOR ROUTER {}", routerName);
+ }
+ } else {
+ for (VpnToDpnList vpnToDpn : vpnDpnList) {
+ dpnList.add(vpnToDpn.getDpnId());
+ }
+ }
+ return dpnList;
+ }
+*/
+
+ public boolean getSwitchStatus(BigInteger switchId){
+ NodeId nodeId = new NodeId("openflow:" + switchId);
+ LOG.debug("Querying switch with dpnId {} is up/down", nodeId);
+ InstanceIdentifier<Node> nodeInstanceId = InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, new NodeKey(nodeId)).build();
+ Optional<Node> nodeOptional = NatUtil.read(dataBroker,LogicalDatastoreType.OPERATIONAL,nodeInstanceId);
+ if (nodeOptional.isPresent()) {
+ LOG.debug("Switch {} is up", nodeId);
+ return true;
+ }
+ LOG.debug("Switch {} is down", nodeId);
+ return false;
+ }
+
+ public List<BucketInfo> handleGroupInPrimarySwitch() {
+ List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
+ List<ActionInfo> listActionInfoPrimary = new ArrayList<ActionInfo>();
+ listActionInfoPrimary.add(new ActionInfo(ActionType.nx_resubmit,
+ new String[]{String.valueOf(NatConstants.TERMINATING_SERVICE_TABLE)}));
+ BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
+ listBucketInfo.add(bucketPrimary);
+ return listBucketInfo;
+ }
+
+ public List<BucketInfo> handleGroupInNeighborSwitches(BigInteger dpnId, String routerName, BigInteger naptSwitch) {
+ List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
+ String ifNamePrimary;
+ Long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ if (routerId == NatConstants.INVALID_ID) {
+ LOG.error("Invalid routerId returned for routerName {}",routerName);
+ return listBucketInfo;
+ }
+ ifNamePrimary = getTunnelInterfaceName(dpnId, naptSwitch);
+ if (ifNamePrimary != null) {
+ LOG.debug("TunnelInterface {} between ordinary switch {} and naptSwitch {}",ifNamePrimary,dpnId,naptSwitch);
+ List<ActionInfo> listActionInfoPrimary = getEgressActionsForInterface(ifNamePrimary, routerId);
+ BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
+ listBucketInfo.add(bucketPrimary);
+ } else {
+ LOG.debug("No TunnelInterface between ordinary switch {} and naptSwitch {}",dpnId,naptSwitch);
+ }
+ return listBucketInfo;
+ }
+
+ protected void installSnatGroupEntry(BigInteger dpnId, List<BucketInfo> bucketInfo, String routerName) {
+ GroupEntity groupEntity = null;
+ try {
+ long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
+ LOG.debug("install SnatMissEntry for groupId {} for dpnId {} for router {}", groupId, dpnId,routerName);
+ groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
+ GroupTypes.GroupAll, bucketInfo);
+ mdsalManager.installGroup(groupEntity);
+ LOG.debug("installed the SNAT to NAPT GroupEntity:{}", groupEntity);
+ } catch (Exception ex) {
+ LOG.error("Failed to install group for groupEntity {} : {}",groupEntity,ex);
+ }
+ }
+
+ private void modifySnatGroupEntry(BigInteger dpnId, List<BucketInfo> bucketInfo, String routerName) {
+ installSnatGroupEntry(dpnId,bucketInfo,routerName);
+ LOG.debug("modified SnatMissEntry for dpnId {} of router {}",dpnId,routerName);
+ }
+
+ protected String getTunnelInterfaceName(BigInteger srcDpId, BigInteger dstDpId) {
+ Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
+ RpcResult<GetTunnelInterfaceNameOutput> rpcResult;
+
+ try {
+ Future<RpcResult<GetTunnelInterfaceNameOutput>> result = itmManager.getTunnelInterfaceName(
+ new GetTunnelInterfaceNameInputBuilder().setSourceDpid(srcDpId).setDestinationDpid(dstDpId).
+// .setTunnelType(tunType).
+ build());
+ rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ tunType = TunnelTypeGre.class;
+ result = itmManager.getTunnelInterfaceName(new GetTunnelInterfaceNameInputBuilder()
+ .setSourceDpid(srcDpId)
+ .setDestinationDpid(dstDpId)
+// .setTunnelType(tunType)
+ .build());
+ rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
+ } else {
+ return rpcResult.getResult().getInterfaceName();
+ }
+ LOG.warn("RPC Call to getTunnelInterfaceId returned with Errors {}", rpcResult.getErrors());
+ } else {
+ return rpcResult.getResult().getInterfaceName();
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when getting tunnel interface Id for tunnel between {} and {} : {}",
+ srcDpId, dstDpId, e);
+ }
+
+ return null;
+ }
+
+ protected List<ActionInfo> getEgressActionsForInterface(String ifName, long routerId) {
+ LOG.debug("getEgressActionsForInterface called for interface {}", ifName);
+ List<ActionInfo> listActionInfo = new ArrayList<ActionInfo>();
+ try {
+ Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
+ interfaceManager.getEgressActionsForInterface(
+ new GetEgressActionsForInterfaceInputBuilder().setIntfName(ifName).setTunnelKey(routerId).build());
+ RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to Get egress actions for interface {} returned with Errors {}"
+ , ifName, rpcResult.getErrors());
+ } else {
+ 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) {
+ 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) {
+ LOG.warn("Exception when egress actions for interface {}", ifName, e);
+ }
+ return listActionInfo;
+ }
+
+ public boolean updateNaptSwitch(String routerName, BigInteger naptSwitchId) {
+ RouterToNaptSwitch naptSwitch = new RouterToNaptSwitchBuilder().setKey(new RouterToNaptSwitchKey(routerName))
+ .setPrimarySwitchId(naptSwitchId).build();
+ try {
+ MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL,
+ NatUtil.buildNaptSwitchRouterIdentifier(routerName), naptSwitch);
+ } catch (Exception ex) {
+ LOG.error("Failed to write naptSwitch {} for router {} in ds",
+ naptSwitchId,routerName);
+ return false;
+ }
+ LOG.debug("Successfully updated naptSwitch {} for router {} in ds",
+ naptSwitchId,routerName);
+ return true;
+ }
+
+ /*public FlowEntity buildSnatFlowEntity(BigInteger dpId, String routerName, long groupId, int addordel) {
+
+ FlowEntity flowEntity;
+ long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ if (routerId == NatConstants.INVALID_ID) {
+ LOG.error("Invalid routerId returned for routerName {}",routerName);
+ return null;
+ }
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[]{ 0x0800L }));
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ BigInteger.valueOf(routerId), MetaDataUtil.METADATA_MASK_VRFID }));
+
+ String flowRef = getFlowRefSnat(dpId, NatConstants.PSNAT_TABLE, routerName);
+
+ if (addordel == NatConstants.ADD_FLOW) {
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ List<ActionInfo> actionsInfo = new ArrayList<ActionInfo>();
+
+ ActionInfo actionSetField = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
+ BigInteger.valueOf(routerId)}) ;
+ actionsInfo.add(actionSetField);
+ LOG.debug("Setting the tunnel to the list of action infos {}", actionsInfo);
+ actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
+ instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfo));
+
+ flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
+ NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_SNAT_TABLE, matches, instructions);
+ } else {
+ flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
+ NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_SNAT_TABLE, matches, null);
+ }
+ return flowEntity;
+ }*/
+
+ public FlowEntity buildSnatFlowEntity(BigInteger dpId, String routerName, long groupId, long routerVpnId, int addordel) {
+
+ FlowEntity flowEntity;
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[]{ 0x0800L }));
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ BigInteger.valueOf(routerVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
+
+ String flowRef = getFlowRefSnat(dpId, NatConstants.PSNAT_TABLE, routerName);
+
+ if (addordel == NatConstants.ADD_FLOW) {
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ List<ActionInfo> actionsInfo = new ArrayList<ActionInfo>();
+
+ ActionInfo actionSetField = new ActionInfo(ActionType.set_field_tunnel_id, new BigInteger[] {
+ BigInteger.valueOf(routerVpnId)}) ;
+ actionsInfo.add(actionSetField);
+ LOG.debug("Setting the tunnel to the list of action infos {}", actionsInfo);
+ actionsInfo.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
+ instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfo));
+
+ flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
+ NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_SNAT_TABLE, matches, instructions);
+ } else {
+ flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.PSNAT_TABLE, flowRef,
+ NatConstants.DEFAULT_PSNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_SNAT_TABLE, matches, null);
+ }
+ return flowEntity;
+ }
+
+ private String getFlowRefSnat(BigInteger dpnId, short tableId, String routerID) {
+ return new StringBuilder().append(NatConstants.SNAT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
+ append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
+ }
+
+ /*protected void installSnatFlows(String routerName,Long routerId,BigInteger naptSwitch) {
+ //36 -> 46 ..Install flow forwarding packet to table46 from table36
+ LOG.debug("installTerminatingServiceTblEntry in naptswitch with dpnId {} for routerName {}", naptSwitch, routerName);
+ externalRouterListener.installTerminatingServiceTblEntry(naptSwitch, routerName);
+
+ //Install default flows punting to controller in table 46(OutBoundNapt table)
+ LOG.debug("installOutboundMissEntry in naptswitch with dpnId {} for routerName {}", naptSwitch, routerName);
+ externalRouterListener.installOutboundMissEntry(routerName, naptSwitch);
+
+ //Table 47 point to table 21 for inbound traffic
+ LOG.debug("installNaptPfibEntry in naptswitch with dpnId {} for routerId {}", naptSwitch, routerId);
+ externalRouterListener.installNaptPfibEntry(naptSwitch, routerId);
+
+ String vpnName = getExtNetworkVpnName(routerId);
+ if(vpnName != null) {
+ //Table 47 point to table 21 for outbound traffic
+ long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
+ if(vpnId > 0) {
+ LOG.debug("installNaptPfibEntry fin naptswitch with dpnId {} for vpnId {}", naptSwitch, vpnId);
+ externalRouterListener.installNaptPfibEntry(naptSwitch, vpnId);
+ } else {
+ LOG.debug("Associated vpnId not found for router {}",routerId);
+ }
+
+ //Install Fib entries for ExternalIps & program 36 -> 44
+ List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,routerId);
+ if (externalIps != null) {
+ for (String externalIp : externalIps) {
+ LOG.debug("advToBgpAndInstallFibAndTsFlows in naptswitch id {} with vpnName {} and externalIp {}",
+ naptSwitch, vpnName, externalIp);
+ externalRouterListener.advToBgpAndInstallFibAndTsFlows(naptSwitch, NatConstants.INBOUND_NAPT_TABLE,
+ vpnName, routerId, externalIp, vpnService, fibService, bgpManager, dataBroker, LOG);
+ LOG.debug("Successfully added fib entries in naptswitch {} for router {} with external IP {}", naptSwitch,
+ routerId, externalIp);
+ }
+ } else {
+ LOG.debug("External Ip not found for routerId {}",routerId);
+ }
+ } else {
+ LOG.debug("Associated vpnName not found for router {}",routerId);
+ }
+ }*/
+
+ protected void installSnatFlows(String routerName,Long routerId,BigInteger naptSwitch,Long routerVpnId) {
+
+ if(routerId.equals(routerVpnId)) {
+ LOG.debug("Installing flows for router with internalvpnId");
+ //36 -> 46 ..Install flow forwarding packet to table46 from table36
+ LOG.debug("installTerminatingServiceTblEntry in naptswitch with dpnId {} for routerName {} with routerId {}",
+ naptSwitch, routerName,routerId);
+ externalRouterListener.installTerminatingServiceTblEntry(naptSwitch, routerName);
+
+ //Install default flows punting to controller in table 46(OutBoundNapt table)
+ LOG.debug("installOutboundMissEntry in naptswitch with dpnId {} for routerName {} with routerId {}",
+ naptSwitch, routerName, routerId);
+ externalRouterListener.createOutboundTblEntry(naptSwitch, routerId);
+
+ //Table 47 point to table 21 for inbound traffic
+ LOG.debug("installNaptPfibEntry in naptswitch with dpnId {} for router {}", naptSwitch, routerId);
+ externalRouterListener.installNaptPfibEntry(naptSwitch, routerId);
+ } else {
+ //36 -> 46 ..Install flow forwarding packet to table46 from table36
+ LOG.debug("installTerminatingServiceTblEntry in naptswitch with dpnId {} for routerName {} with BgpVpnId {}",
+ naptSwitch, routerName, routerVpnId);
+ externalRouterListener.installTerminatingServiceTblEntryWithUpdatedVpnId(naptSwitch, routerName, routerVpnId);
+
+ //Install default flows punting to controller in table 46(OutBoundNapt table)
+ LOG.debug("installOutboundMissEntry in naptswitch with dpnId {} for routerName {} with BgpVpnId {}",
+ naptSwitch, routerName, routerVpnId);
+ externalRouterListener.createOutboundTblEntryWithBgpVpn(naptSwitch, routerId, routerVpnId);
+
+ //Table 47 point to table 21 for inbound traffic
+ LOG.debug("installNaptPfibEntry in naptswitch with dpnId {} for router {} with BgpVpnId {}",
+ naptSwitch, routerId, routerVpnId);
+ externalRouterListener.installNaptPfibEntryWithBgpVpn(naptSwitch, routerId, routerVpnId);
+ }
+
+ String vpnName = getExtNetworkVpnName(routerId);
+ if(vpnName != null) {
+ //Table 47 point to table 21 for outbound traffic
+ long vpnId = NatUtil.getVpnId(dataBroker, vpnName);
+ if(vpnId > 0) {
+ LOG.debug("installNaptPfibEntry fin naptswitch with dpnId {} for BgpVpnId {}", naptSwitch, vpnId);
+ externalRouterListener.installNaptPfibEntry(naptSwitch, vpnId);
+ } else {
+ LOG.debug("Associated BgpvpnId not found for router {}",routerId);
+ }
+
+ //Install Fib entries for ExternalIps & program 36 -> 44
+ List<String> externalIps = NatUtil.getExternalIpsForRouter(dataBroker,routerId);
+ if (externalIps != null) {
+ for (String externalIp : externalIps) {
+ LOG.debug("advToBgpAndInstallFibAndTsFlows in naptswitch id {} with vpnName {} and externalIp {}",
+ naptSwitch, vpnName, externalIp);
+ externalRouterListener.advToBgpAndInstallFibAndTsFlows(naptSwitch, NatConstants.INBOUND_NAPT_TABLE,
+ vpnName, routerId, externalIp, vpnService, fibService, bgpManager, dataBroker, LOG);
+ LOG.debug("Successfully added fib entries in naptswitch {} for router {} with external IP {}", naptSwitch,
+ routerId, externalIp);
+ }
+ } else {
+ LOG.debug("External Ip not found for routerId {}",routerId);
+ }
+ } else {
+ LOG.debug("Associated vpnName not found for router {}",routerId);
+ }
+ }
+}
\ 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.natservice.internal;
+
+import java.math.BigInteger;
+
+
+public class NatConstants {
+ public static final short INBOUND_NAPT_TABLE = 44;
+ public static final short OUTBOUND_NAPT_TABLE = 46;
+ public static final short NAPT_PFIB_TABLE = 47;
+ public static final short TERMINATING_SERVICE_TABLE = 36;
+ public static final short DEFAULT_NAPT_FLOW_PRIORITY = 10;
+ public static final String NAPT_FLOW_NAME = "SNAT";
+ public static BigInteger COOKIE_NAPT_BASE = new BigInteger("8000000", 16);
+ public static final String NAPT_FLOWID_PREFIX = "SNAT.";
+ public static final String FLOWID_SEPARATOR = ".";
+ public static final int DEFAULT_NAPT_IDLE_TIMEOUT = 300;
+ public static int EVENT_QUEUE_LENGTH = 1000000;
+ public static final short PDNAT_TABLE = 25;
+ public static final short DNAT_TABLE = 27;
+ public static final short SNAT_TABLE = 28;
+ public static final short PSNAT_TABLE = 26;
+ public static final short L3_FIB_TABLE = 21;
+ public static final String FLOWID_PREFIX = "L3.";
+ public static final int DEFAULT_DNAT_FLOW_PRIORITY = 10;
+ public static final BigInteger COOKIE_DNAT_TABLE = new BigInteger("8000004", 16);
+ public static final long INVALID_ID = -1;
+ public static final BigInteger COOKIE_OUTBOUND_NAPT_TABLE = new BigInteger("8000008", 16);
+ public static final short DEFAULT_SNAT_FLOW_PRIORITY = 10;
+ public static final short DEFAULT_PSNAT_FLOW_PRIORITY = 5;
+ public static final String SNAT_FLOW_NAME = "SNAT";
+ public static final String SNAT_FLOWID_PREFIX = "SNAT.";
+ public static final BigInteger COOKIE_SNAT_TABLE = new BigInteger("8000006", 16);
+ public static final String SNAT_IDPOOL_NAME = "snatGroupIdPool";
+ public static final long SNAT_ID_LOW_VALUE = 200000L;
+ public static final long SNAT_ID_HIGH_VALUE = 225000L;
+ public static final int DEFAULT_TS_FLOW_PRIORITY = 10;
+ public static final BigInteger COOKIE_TS_TABLE = new BigInteger("8000002", 16);
+ public static final short DEFAULT_PREFIX = 32;
+
+ // Flow Actions
+ public static final int ADD_FLOW = 0;
+ public static final int DEL_FLOW = 1;
+
+}
--- /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.natservice.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.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;
+
+public class NatNodeEventListener extends AbstractDataChangeListener<Node> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(NatNodeEventListener.class);
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private NaptSwitchHA naptSwitchHA;
+
+ public NatNodeEventListener(final DataBroker db,final NaptSwitchHA napt) {
+ super(Node.class);
+ naptSwitchHA = napt;
+ registerListener(db);
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), NatNodeEventListener.this, AsyncDataBroker.DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("NatNodeEventListener: DataChange listener registration fail!", e);
+ throw new IllegalStateException("NatNodeEventListener: 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) {
+ LOG.debug("NatNodeEventListener: Node removed received");
+ NodeId nodeId = del.getId();
+ String[] node = nodeId.getValue().split(":");
+ if(node.length < 2) {
+ LOG.warn("Unexpected nodeId {}", nodeId.getValue());
+ return;
+ }
+ BigInteger dpnId = new BigInteger(node[1]);
+ LOG.debug("NodeId removed is {}",dpnId);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Node> identifier, Node original, Node update) {
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Node> identifier, Node add) {
+ LOG.debug("NatNodeEventListener: Node added received");
+ NodeId nodeId = add.getId();
+ String[] node = nodeId.getValue().split(":");
+ if(node.length < 2) {
+ LOG.warn("Unexpected nodeId {}", nodeId.getValue());
+ return;
+ }
+ BigInteger dpnId = new BigInteger(node[1]);
+ LOG.debug("NodeId added is {}",dpnId);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("NatNodeEventListener Closed");
+ }
+}
--- /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.natservice.internal;
+
+import org.opendaylight.bgpmanager.api.IBgpManager;
+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.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.controller.md.sal.binding.api.NotificationService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.FibRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.NeutronvpnService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.VpnRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+
+public class NatServiceProvider implements BindingAwareProvider, AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(NatServiceProvider.class);
+ private IMdsalApiManager mdsalManager;
+ private RpcProviderRegistry rpcProviderRegistry;
+ private NotificationService notificationService;
+ private ItmRpcService itmManager;
+ private FloatingIPListener floatingIpListener;
+ private ExternalNetworkListener extNwListener;
+ private NaptManager naptManager;
+ private NaptEventHandler naptEventHandler;
+ private BlockingQueue<NAPTEntryEvent> naptEventQueue;
+ private ExternalNetworksChangeListener externalNetworksChangeListener;
+ private ExternalRoutersListener externalRouterListener;
+ private NaptPacketInHandler naptPacketInHandler;
+ private EventDispatcher eventDispatcher;
+ private IBgpManager bgpManager;
+ private NaptFlowRemovedEventHandler naptFlowRemovedEventHandler;
+ private InterfaceStateEventListener interfaceStateEventListener;
+ private NatNodeEventListener natNodeEventListener;
+ private NAPTSwitchSelector naptSwitchSelector;
+ private RouterPortsListener routerPortsListener;
+
+ public NatServiceProvider(RpcProviderRegistry rpcProviderRegistry) {
+ this.rpcProviderRegistry = rpcProviderRegistry;
+ }
+
+ public void setNotificationService(NotificationService notificationService) {
+ this.notificationService = notificationService;
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ public void setBgpManager(IBgpManager bgpManager) {
+ LOG.debug("BGP Manager reference initialized");
+ this.bgpManager = bgpManager;
+ }
+
+ @Override
+ public void close() throws Exception {
+ floatingIpListener.close();
+ extNwListener.close();
+ externalNetworksChangeListener.close();
+ externalRouterListener.close();
+ routerPortsListener.close();
+ }
+
+ @Override
+ public void onSessionInitiated(ProviderContext session) {
+ LOG.info("NAT Manager Provider Session Initiated");
+ try {
+ //Get the DataBroker, PacketProcessingService, IdManagerService and the OdlInterfaceRpcService instances
+ final DataBroker dataBroker = session.getSALService(DataBroker.class);
+ PacketProcessingService pktProcessingService = session.getRpcService(PacketProcessingService.class);
+ IdManagerService idManager = rpcProviderRegistry.getRpcService(IdManagerService.class);
+ OdlInterfaceRpcService interfaceService = rpcProviderRegistry.getRpcService(OdlInterfaceRpcService.class);
+ NeutronvpnService neutronvpnService = rpcProviderRegistry.getRpcService(NeutronvpnService.class);
+ itmManager = rpcProviderRegistry.getRpcService(ItmRpcService.class);
+
+ //Instantiate FloatingIPListener and set the MdsalManager and OdlInterfaceRpcService in it.
+ floatingIpListener = new FloatingIPListener(dataBroker);
+ floatingIpListener.setInterfaceManager(interfaceService);
+ floatingIpListener.setMdsalManager(mdsalManager);
+
+ //Instantiate ExternalNetworkListener and set the MdsalManager in it.
+ extNwListener = new ExternalNetworkListener(dataBroker);
+ extNwListener.setMdsalManager(mdsalManager);
+
+ //Instantiate NaptManager and set the IdManagerService in it.
+ naptManager = new NaptManager(dataBroker);
+ naptManager.setIdManager(idManager);
+
+ //Instantiate NaptEventHandler and start it as a Thread.
+ naptEventHandler = new NaptEventHandler(dataBroker);
+ naptEventHandler.setMdsalManager(mdsalManager);
+ naptEventHandler.setNaptManager(naptManager);
+ naptEventQueue = new ArrayBlockingQueue<>(NatConstants.EVENT_QUEUE_LENGTH);
+ eventDispatcher = new EventDispatcher(naptEventQueue, naptEventHandler);
+ new Thread(eventDispatcher).start();
+
+ //Instantiate NaptPacketInHandler and register it in the notification service.
+ naptPacketInHandler = new NaptPacketInHandler(eventDispatcher);
+ notificationService.registerNotificationListener(naptPacketInHandler);
+
+ //Floating ip Handler
+ VpnRpcService vpnService = rpcProviderRegistry.getRpcService(VpnRpcService.class);
+ FibRpcService fibService = rpcProviderRegistry.getRpcService(FibRpcService.class);
+ VpnFloatingIpHandler handler = new VpnFloatingIpHandler(vpnService, bgpManager, fibService);
+ handler.setBroker(dataBroker);
+ handler.setMdsalManager(mdsalManager);
+ handler.setListener(floatingIpListener);
+ floatingIpListener.setFloatingIpHandler(handler);
+
+ //Instantiate NaptSwitchSelector and set the dataBroker in it.
+ naptSwitchSelector = new NAPTSwitchSelector( dataBroker );
+
+ //Instantiate ExternalRouterListener and set the dataBroker in it.
+ externalRouterListener = new ExternalRoutersListener( dataBroker );
+ externalRouterListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker );
+ externalRouterListener.setMdsalManager(mdsalManager);
+ externalRouterListener.setItmManager(itmManager);
+ externalRouterListener.setInterfaceManager(interfaceService);
+ externalRouterListener.setIdManager(idManager);
+ externalRouterListener.setNaptManager(naptManager);
+ externalRouterListener.setBgpManager(bgpManager);
+ externalRouterListener.setFibService(fibService);
+ externalRouterListener.setVpnService(vpnService);
+ externalRouterListener.setNaptSwitchSelector(naptSwitchSelector);
+ externalRouterListener.setNaptEventHandler(naptEventHandler);
+ externalRouterListener.setNaptPacketInHandler(naptPacketInHandler);
+
+ //Instantiate ExternalNetworksChangeListener and set the dataBroker in it.
+ externalNetworksChangeListener = new ExternalNetworksChangeListener( dataBroker );
+ externalNetworksChangeListener.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
+ externalNetworksChangeListener.setMdsalManager(mdsalManager);
+ externalNetworksChangeListener.setInterfaceManager(interfaceService);
+ externalNetworksChangeListener.setFloatingIpListener(floatingIpListener);
+ externalNetworksChangeListener.setBgpManager(bgpManager);
+ externalNetworksChangeListener.setFibService(fibService);
+ externalNetworksChangeListener.setVpnService(vpnService);
+ externalNetworksChangeListener.setExternalRoutersListener(externalRouterListener);
+ externalNetworksChangeListener.setNaptManager(naptManager);
+ externalNetworksChangeListener.setExternalRoutersListener(externalRouterListener);
+
+ //Instantiate NaptFlowRemovedHandler and register it in the notification service.
+ naptFlowRemovedEventHandler = new NaptFlowRemovedEventHandler(eventDispatcher, dataBroker, naptPacketInHandler, mdsalManager, naptManager);
+ notificationService.registerNotificationListener(naptFlowRemovedEventHandler);
+
+ //Instantiate interfaceStateEventListener and set the MdsalManager in it.
+ interfaceStateEventListener = new InterfaceStateEventListener(dataBroker);
+ interfaceStateEventListener.setMdsalManager(mdsalManager);
+ interfaceStateEventListener.setFloatingIpListener(floatingIpListener);
+ interfaceStateEventListener.setNeutronVpnService(neutronvpnService);
+ interfaceStateEventListener.setNaptManager(naptManager);
+
+ SNATDefaultRouteProgrammer defaultRouteProgrammer = new SNATDefaultRouteProgrammer(mdsalManager);
+ DpnInVpnListener dpnInVpnListener = new DpnInVpnListener(dataBroker);
+ dpnInVpnListener.setDefaultProgrammer(defaultRouteProgrammer);
+ notificationService.registerNotificationListener(dpnInVpnListener);
+
+ externalRouterListener.setDefaultProgrammer(defaultRouteProgrammer);
+
+ NaptSwitchHA naptSwitchHA = new NaptSwitchHA(dataBroker,naptSwitchSelector);
+ naptSwitchHA.setIdManager(idManager);
+ naptSwitchHA.setInterfaceManager(interfaceService);
+ naptSwitchHA.setMdsalManager(mdsalManager);
+ naptSwitchHA.setItmManager(itmManager);
+ naptSwitchHA.setBgpManager(bgpManager);
+ naptSwitchHA.setFibService(fibService);
+ naptSwitchHA.setVpnService(vpnService);
+ naptSwitchHA.setExternalRoutersListener(externalRouterListener);
+
+ natNodeEventListener = new NatNodeEventListener(dataBroker,naptSwitchHA);
+
+ dpnInVpnListener.setNaptSwitchHA(naptSwitchHA);
+ dpnInVpnListener.setMdsalManager(mdsalManager);
+ dpnInVpnListener.setIdManager(idManager);
+
+ routerPortsListener = new RouterPortsListener(dataBroker);
+
+ RouterDpnChangeListener routerDpnChangeListener = new RouterDpnChangeListener(dataBroker);
+ routerDpnChangeListener.setDefaultProgrammer(defaultRouteProgrammer);
+ routerDpnChangeListener.setIdManager(idManager);
+ routerDpnChangeListener.setMdsalManager(mdsalManager);
+ routerDpnChangeListener.setNaptSwitchHA(naptSwitchHA);
+
+ RouterToVpnListener routerToVpnListener = new RouterToVpnListener(dataBroker);
+ routerToVpnListener.setFloatingIpListener(floatingIpListener);
+ routerToVpnListener.setInterfaceManager(interfaceService);
+ routerToVpnListener.setExternalRoutersListener(externalRouterListener);
+ notificationService.registerNotificationListener(routerToVpnListener);
+ } catch (Exception e) {
+ LOG.error("Error initializing NAT Manager service", e);
+ }
+ }
+}
--- /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.natservice.internal;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceToVpnId;
+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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ext.routers.Routers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ext.routers.RoutersKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.ips.counter.ExternalCounters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.ips.counter.ExternalCountersKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.ips.counter.external.counters.ExternalIpCounter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.IntextIpProtocolTypeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.IpPortMapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.ip.port.map.IpPortExternal;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.router.id.name.RouterIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.router.id.name.RouterIdsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.RouterToVpnMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.router.to.vpn.mapping.Routermapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.router.to.vpn.mapping.RoutermappingKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.IntipPortMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.IntipPortMapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPort;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.intip.port.map.IpPortKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.snatint.ip.port.map.intip.port.map.ip.port.IntIpProtoTypeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.FloatingIpInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.NeutronRouterDpns;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.Subnetmaps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.VpnMaps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.Subnetmap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.vpnmaps.VpnMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.vpnmaps.VpnMapKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+
+import com.google.common.base.Optional;
+
+import org.opendaylight.bgpmanager.api.IBgpManager;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.networks.Networks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.networks.NetworksKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.RouterPorts;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.RouterPortsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.Ports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.PortsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ExternalNetworks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitch;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.napt.switches.RouterToNaptSwitchKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.DpnEndpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfoKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.ports.IpMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.ports.IpMappingKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.IntextIpPortMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.IpPortMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+
+
+public class NatUtil {
+
+ private static String OF_URI_SEPARATOR = ":";
+ private static final Logger LOG = LoggerFactory.getLogger(NatUtil.class);
+
+ /*
+ getCookieSnatFlow() computes and returns a unique cookie value for the NAT flows using the router ID as the reference value.
+ */
+ public static BigInteger getCookieSnatFlow(long routerId) {
+ return NatConstants.COOKIE_NAPT_BASE.add(new BigInteger("0110000", 16)).add(
+ BigInteger.valueOf(routerId));
+ }
+
+ /*
+ getCookieNaptFlow() computes and returns a unique cookie value for the NAPT flows using the router ID as the reference value.
+ */
+ public static BigInteger getCookieNaptFlow(long routerId) {
+ return NatConstants.COOKIE_NAPT_BASE.add(new BigInteger("0111000", 16)).add(
+ BigInteger.valueOf(routerId));
+ }
+
+ /*
+ getVpnId() returns the VPN ID from the VPN name
+ */
+ public static long getVpnId(DataBroker broker, String vpnName) {
+ if(vpnName == null) {
+ return NatConstants.INVALID_ID;
+ }
+
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
+ = getVpnInstanceToVpnIdIdentifier(vpnName);
+ Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
+ = read(broker, LogicalDatastoreType.CONFIGURATION, id);
+
+ long vpnId = NatConstants.INVALID_ID;
+ if(vpnInstance.isPresent()) {
+ vpnId = vpnInstance.get().getVpnId();
+ }
+ return vpnId;
+ }
+
+ public static Long getVpnId(DataBroker broker, long routerId){
+ //Get the external network ID from the ExternalRouter model
+ Uuid networkId = NatUtil.getNetworkIdFromRouterId(broker, routerId);
+ if(networkId == null ){
+ LOG.error("NAT Service : networkId is null");
+ return null;
+ }
+
+ //Get the VPN ID from the ExternalNetworks model
+ Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(broker, networkId);
+ if(vpnUuid == null ){
+ LOG.error("NAT Service : vpnUuid is null");
+ return null;
+ }
+ Long vpnId = NatUtil.getVpnId(broker, vpnUuid.getValue());
+ return vpnId;
+ }
+
+ static InstanceIdentifier<RouterPorts> getRouterPortsId(String routerId) {
+ return InstanceIdentifier.builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerId)).build();
+ }
+
+ static InstanceIdentifier<Routermapping> getRouterVpnMappingId(String routerId) {
+ return InstanceIdentifier.builder(RouterToVpnMapping.class).child(Routermapping.class, new RoutermappingKey(routerId)).build();
+ }
+
+ static InstanceIdentifier<Ports> getPortsIdentifier(String routerId, String portName) {
+ return InstanceIdentifier.builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerId))
+ .child(Ports.class, new PortsKey(portName)).build();
+ }
+
+ static InstanceIdentifier<IpMapping> getIpMappingIdentifier(String routerId, String portName, String internalIp) {
+ return InstanceIdentifier.builder(FloatingIpInfo.class).child(RouterPorts.class, new RouterPortsKey(routerId))
+ .child(Ports.class, new PortsKey(portName))
+ .child(IpMapping.class, new IpMappingKey(internalIp)).build();
+ }
+
+ /*
+ getVpnInstanceToVpnIdIdentifier() returns the VPN instance from the below model using the VPN name as the key.
+ list vpn-instance {
+ key "vpn-instance-name"
+ leaf vpn-instance-name {
+ type string;
+ }
+ leaf vpn-id {
+ type uint32;
+ }
+ leaf vrf-id {
+ type string;
+ }
+ }
+ */
+
+ static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
+ getVpnInstanceToVpnIdIdentifier(String vpnName) {
+ return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
+ .child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance.class,
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
+ }
+
+ /*
+ getFlowRef() returns a string identfier for the SNAT flows using the router ID as the reference.
+ */
+ public static String getFlowRef(BigInteger dpnId, short tableId, long routerID, String ip) {
+ return new StringBuffer().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
+ append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID)
+ .append(NatConstants.FLOWID_SEPARATOR).append(ip).toString();
+ }
+
+ public static String getNaptFlowRef(BigInteger dpnId, short tableId, String routerID, String ip, int port) {
+ return new StringBuffer().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
+ append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).append(NatConstants.FLOWID_SEPARATOR).append(ip).
+ append(NatConstants.FLOWID_SEPARATOR).append(port).toString();
+ }
+
+ /*
+ getNetworkIdFromRouterId() returns the network-id from the below model using the router-id as the key
+ container ext-routers {
+ list routers {
+ key router-name;
+ leaf router-name { type string; }
+ leaf network-id { type yang:uuid; }
+ leaf enable-snat { type boolean; }
+ leaf-list external-ips {
+ type string; //format - ipaddress\prefixlength
+ }
+ leaf-list subnet-ids { type yang:uuid; }
+ }
+ }
+
+ */
+ static Uuid getNetworkIdFromRouterId(DataBroker broker, long routerId) {
+ String routerName = getRouterName(broker, routerId);
+ InstanceIdentifier id = buildRouterIdentifier(routerName);
+ Optional<Routers> routerData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
+ if (routerData.isPresent()) {
+ return routerData.get().getNetworkId();
+ }
+ return null;
+ }
+
+ static InstanceIdentifier<Routers> buildRouterIdentifier(String routerId) {
+ InstanceIdentifier<Routers> routerInstanceIndentifier = InstanceIdentifier.builder(ExtRouters.class).child
+ (Routers.class, new RoutersKey(routerId)).build();
+ return routerInstanceIndentifier;
+ }
+
+ /*
+ * getEnableSnatFromRouterId() returns IsSnatEnabled true is routerID is present in external n/w otherwise returns false
+ */
+ static boolean isSnatEnabledForRouterId(DataBroker broker, String routerId){
+ InstanceIdentifier id = buildRouterIdentifier(routerId);
+ Optional<Routers> routerData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
+ if (routerData.isPresent()) {
+ return routerData.get().isEnableSnat();
+ }
+ return false;
+ }
+ /*
+ getVpnIdfromNetworkId() returns the vpnid from the below model using the network ID as the key.
+ container external-networks {
+ list networks {
+ key id;
+ leaf id {
+ type yang:uuid;
+ }
+ leaf vpnid { type yang:uuid; }
+ leaf-list router-ids { type yang:uuid; }
+ leaf-list subnet-ids{ type yang:uuid; }
+ }
+ }
+ */
+ public static Uuid getVpnIdfromNetworkId(DataBroker broker, Uuid networkId) {
+ InstanceIdentifier id = buildNetworkIdentifier(networkId);
+ Optional<Networks> networkData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
+ if (networkData.isPresent()) {
+ return networkData.get().getVpnid();
+ }
+ return null;
+ }
+
+ static String getAssociatedExternalNetwork(DataBroker dataBroker, String routerId) {
+ InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerId);
+ Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+ if (routerData.isPresent()) {
+ Uuid networkId = routerData.get().getNetworkId();
+ if(networkId != null) {
+ return networkId.getValue();
+ }
+ }
+ return null;
+ }
+
+ private static InstanceIdentifier<Networks> buildNetworkIdentifier(Uuid networkId) {
+ InstanceIdentifier<Networks> network = InstanceIdentifier.builder(ExternalNetworks.class).child
+ (Networks.class, new NetworksKey(networkId)).build();
+ return network;
+ }
+
+
+
+
+ /*
+ getNaptSwitchesDpnIdsfromRouterId() returns the primary-switch-id and the secondary-switch-id in a array using the router-id; as the key.
+ container napt-switches {
+ list router-to-napt-switch {
+ key router-id;
+ leaf router-id { type uint32; }
+ leaf primary-switch-id { type uint64; }
+ leaf secondary-switch-id { type uint64; }
+ }
+ }
+ */
+ public static BigInteger getPrimaryNaptfromRouterId(DataBroker broker, Long routerId) {
+ // convert routerId to Name
+ String routerName = getRouterName(broker, routerId);
+ InstanceIdentifier id = buildNaptSwitchIdentifier(routerName);
+ Optional<RouterToNaptSwitch> routerToNaptSwitchData = read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ if (routerToNaptSwitchData.isPresent()) {
+ RouterToNaptSwitch routerToNaptSwitchInstance = routerToNaptSwitchData.get();
+ return routerToNaptSwitchInstance.getPrimarySwitchId();
+ }
+ return null;
+ }
+
+ private static InstanceIdentifier<RouterToNaptSwitch> buildNaptSwitchIdentifier(String routerId) {
+ InstanceIdentifier<RouterToNaptSwitch> rtrNaptSw = InstanceIdentifier.builder(NaptSwitches.class).child
+ (RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerId)).build();
+ return rtrNaptSw;
+ }
+
+ public static String getRouterName(DataBroker broker, Long routerId) {
+ InstanceIdentifier id = buildRouterIdentifier(routerId);
+ Optional<RouterIds> routerIdsData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
+ if (routerIdsData.isPresent()) {
+ RouterIds routerIdsInstance = routerIdsData.get();
+ return routerIdsInstance.getRouterName();
+ }
+ return null;
+ }
+
+ private static InstanceIdentifier<RouterIds> buildRouterIdentifier(Long routerId) {
+ InstanceIdentifier<RouterIds> routerIds = InstanceIdentifier.builder(RouterIdName.class).child
+ (RouterIds.class, new RouterIdsKey(routerId)).build();
+ return routerIds;
+ }
+
+ 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;
+ }
+
+ static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String vrfId) {
+ return InstanceIdentifier.builder(VpnInstanceOpData.class)
+ .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vrfId)).build();
+ }
+
+ public static long readVpnId(DataBroker broker, String vpnName) {
+
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
+ = getVpnInstanceToVpnIdIdentifier(vpnName);
+ Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
+ = read(broker, LogicalDatastoreType.CONFIGURATION, id);
+
+ long vpnId = NatConstants.INVALID_ID;
+ if(vpnInstance.isPresent()) {
+ vpnId = vpnInstance.get().getVpnId();
+ }
+ return vpnId;
+ }
+
+ public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, BigInteger cookie) {
+ FlowEntity flowEntity = new FlowEntity(dpnId);
+ flowEntity.setTableId(tableId);
+ flowEntity.setCookie(cookie);
+ return flowEntity;
+ }
+
+ public static long getIpAddress(byte[] rawIpAddress) {
+ return (((rawIpAddress[0] & 0xFF) << (3 * 8)) + ((rawIpAddress[1] & 0xFF) << (2 * 8))
+ + ((rawIpAddress[2] & 0xFF) << (1 * 8)) + (rawIpAddress[3] & 0xFF)) & 0xffffffffL;
+ }
+
+ public static String getFlowRef(BigInteger dpnId, short tableId, InetAddress destPrefix) {
+ return new StringBuilder(64).append(NatConstants.FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
+ .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
+ .append(destPrefix.getHostAddress()).toString();
+ }
+
+ public static String getEndpointIpAddressForDPN(DataBroker broker, BigInteger dpnId) {
+ String nextHopIp = null;
+ InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
+ InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, new DPNTEPsInfoKey(dpnId)).build();
+ Optional<DPNTEPsInfo> tunnelInfo = read(broker, LogicalDatastoreType.CONFIGURATION, tunnelInfoId);
+ if (tunnelInfo.isPresent()) {
+ List<TunnelEndPoints> nexthopIpList = tunnelInfo.get().getTunnelEndPoints();
+ if (nexthopIpList != null && !nexthopIpList.isEmpty()) {
+ nextHopIp = nexthopIpList.get(0).getIpAddress().getIpv4Address().getValue();
+ }
+ }
+ return nextHopIp;
+ }
+
+ /*
+ getVpnRd returns the rd (route distinguisher) which is the VRF ID from the below model using the vpnName
+ list vpn-instance {
+ key "vpn-instance-name"
+ leaf vpn-instance-name {
+ type string;
+ }
+ leaf vpn-id {
+ type uint32;
+ }
+ leaf vrf-id {
+ type string;
+ }
+ }
+ */
+ public static String getVpnRd(DataBroker broker, String vpnName) {
+
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
+ = getVpnInstanceToVpnIdIdentifier(vpnName);
+ Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
+ = read(broker, LogicalDatastoreType.CONFIGURATION, id);
+
+ String rd = null;
+ if(vpnInstance.isPresent()) {
+ rd = vpnInstance.get().getVrfId();
+ }
+ return rd;
+ }
+
+ /* getExternalIPPortMap() returns the internal IP and the port for the querried router ID, external IP and the port.
+ container intext-ip-port-map {
+ config true;
+ list ip-port-mapping {
+ key router-id;
+ leaf router-id { type uint32; }
+ list intext-ip-protocol-type {
+ key protocol;
+ leaf protocol { type protocol-types; }
+ list ip-port-map {
+ key ip-port-internal;
+ description "internal to external ip-port mapping";
+ leaf ip-port-internal { type string; }
+ container ip-port-external {
+ uses ip-port-entity;
+ }
+ }
+ }
+ }
+ }
+ */
+ public static IpPortExternal getExternalIpPortMap(DataBroker broker, Long routerId, String internalIpAddress, String internalPort, NAPTEntryEvent.Protocol protocol) {
+ ProtocolTypes protocolType = NatUtil.getProtocolType(protocol);
+ InstanceIdentifier ipPortMapId = buildIpToPortMapIdentifier(routerId, internalIpAddress, internalPort, protocolType);
+ Optional<IpPortMap> ipPortMapData = read(broker, LogicalDatastoreType.CONFIGURATION, ipPortMapId);
+ if (ipPortMapData.isPresent()) {
+ IpPortMap ipPortMapInstance = ipPortMapData.get();
+ return ipPortMapInstance.getIpPortExternal();
+ }
+ return null;
+ }
+
+ private static InstanceIdentifier<IpPortMap> buildIpToPortMapIdentifier(Long routerId, String internalIpAddress, String internalPort , ProtocolTypes protocolType) {
+ InstanceIdentifier<IpPortMap> ipPortMapId = InstanceIdentifier.builder(IntextIpPortMap.class).child
+ (IpPortMapping.class, new IpPortMappingKey(routerId)).child(IntextIpProtocolType.class, new IntextIpProtocolTypeKey(protocolType))
+ .child(IpPortMap.class, new IpPortMapKey(internalIpAddress + ":" + internalPort)).build();
+ return ipPortMapId;
+ }
+
+ public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, String flowId, int priority, String flowName,
+ BigInteger cookie, List<MatchInfo> listMatchInfo) {
+
+ FlowEntity flowEntity = new FlowEntity(dpnId);
+ flowEntity.setTableId(tableId);
+ flowEntity.setFlowId(flowId);
+ flowEntity.setPriority(priority);
+ flowEntity.setFlowName(flowName);
+ flowEntity.setCookie(cookie);
+ flowEntity.setMatchInfoList(listMatchInfo);
+ return flowEntity;
+ }
+
+ static boolean isVpnInterfaceConfigured(DataBroker broker, String interfaceName)
+ {
+ InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
+ Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
+
+ if (configuredVpnInterface.isPresent()) {
+ return true;
+ }
+ return false;
+ }
+
+ static InstanceIdentifier<VpnInterface> getVpnInterfaceIdentifier(String vpnInterfaceName) {
+ return InstanceIdentifier.builder(VpnInterfaces.class)
+ .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).build();
+ }
+
+ static VpnInterface getConfiguredVpnInterface(DataBroker broker, String interfaceName) {
+ InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
+ Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
+
+ if (configuredVpnInterface.isPresent()) {
+ return configuredVpnInterface.get();
+ }
+ return null;
+ }
+
+ public static String getDpnFromNodeConnectorId(NodeConnectorId portId) {
+ /*
+ * NodeConnectorId is of form 'openflow:dpnid:portnum'
+ */
+ String[] split = portId.getValue().split(OF_URI_SEPARATOR);
+ return split[1];
+ }
+
+ public static BigInteger getDpIdFromInterface(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
+ String lowerLayerIf = ifState.getLowerLayerIf().get(0);
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
+ return new BigInteger(getDpnFromNodeConnectorId(nodeConnectorId));
+ }
+
+
+ /*
+ container vpnMaps {
+ list vpnMap {
+ key vpn-id;
+ leaf vpn-id {
+ type yang:uuid;
+ description "vpn-id";
+ }
+ leaf name {
+ type string;
+ description "vpn name";
+ }
+ leaf tenant-id {
+ type yang:uuid;
+ description "The UUID of the tenant that will own the subnet.";
+ }
+
+ leaf router-id {
+ type yang:uuid;
+ description "UUID of router ";
+ }
+ leaf-list network_ids {
+ type yang:uuid;
+ description "UUID representing the network ";
+ }
+ }
+ }
+ Method returns router Id associated to a VPN
+ */
+
+ public static String getRouterIdfromVpnId(DataBroker broker,String vpnName){
+ InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
+ .child(VpnMap.class, new VpnMapKey(new Uuid(vpnName))).build();
+ Optional<VpnMap> optionalVpnMap = read(broker, LogicalDatastoreType.CONFIGURATION,
+ vpnMapIdentifier);
+ if (optionalVpnMap.isPresent()) {
+ return optionalVpnMap.get().getRouterId().getValue();
+ }
+ return null;
+ }
+
+ static Uuid getVpnForRouter(DataBroker broker, String routerId) {
+ InstanceIdentifier<VpnMaps> vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build();
+ Optional<VpnMaps> optionalVpnMaps = read(broker, LogicalDatastoreType.CONFIGURATION,
+ vpnMapsIdentifier);
+ if (optionalVpnMaps.isPresent() && optionalVpnMaps.get().getVpnMap() != null) {
+ List<VpnMap> allMaps = optionalVpnMaps.get().getVpnMap();
+ if (routerId != null) {
+ for (VpnMap vpnMap : allMaps) {
+ if (vpnMap.getRouterId() != null &&
+ routerId.equals(vpnMap.getRouterId().getValue()) &&
+ !routerId.equals(vpnMap.getVpnId().getValue())) {
+ return vpnMap.getVpnId();
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ static long getAssociatedVpn(DataBroker broker, String routerName) {
+ InstanceIdentifier<Routermapping> routerMappingId = NatUtil.getRouterVpnMappingId(routerName);
+ Optional<Routermapping> optRouterMapping = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, routerMappingId);
+ if(optRouterMapping.isPresent()) {
+ Routermapping routerMapping = optRouterMapping.get();
+ return routerMapping.getVpnId();
+ }
+ return NatConstants.INVALID_ID;
+ }
+
+
+ public static List<VpnToDpnList> getVpnToDpnList(DataBroker dataBroker, String vrfId )
+ {
+ List<VpnToDpnList> vpnDpnList = null;
+
+ InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier
+ .builder(VpnInstanceOpData.class)
+ .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vrfId))
+ .build();
+
+ Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
+
+ if(vpnInstanceOpData.isPresent())
+ {
+ VpnInstanceOpDataEntry vpnInstanceOpDataEntry = vpnInstanceOpData.get();
+ vpnDpnList = vpnInstanceOpDataEntry.getVpnToDpnList();
+ }
+
+ return vpnDpnList;
+ }
+
+ public static String getAssociatedVPN(DataBroker dataBroker, Uuid networkId, Logger log) {
+ Uuid vpnUuid = NatUtil.getVpnIdfromNetworkId(dataBroker, networkId);
+ if(vpnUuid == null ){
+ log.error("No VPN instance associated with ext network {}", networkId);
+ return null;
+ }
+ return vpnUuid.getValue();
+ }
+
+ public static void addPrefixToBGP(IBgpManager bgpManager, String rd, String prefix, String nextHopIp, long label, Logger log) {
+ try {
+ bgpManager.addPrefix(rd, prefix, nextHopIp, (int)label);
+ } catch(Exception e) {
+ log.error("Add prefix failed", e);
+ }
+ }
+
+ static InstanceIdentifier<Ports> buildPortToIpMapIdentifier(String routerId, String portName) {
+ InstanceIdentifier<Ports> ipPortMapId = InstanceIdentifier.builder(FloatingIpInfo.class).child
+ (RouterPorts.class, new RouterPortsKey(routerId)).child(Ports.class, new PortsKey(portName)).build();
+ return ipPortMapId;
+ }
+
+ static InstanceIdentifier<RouterPorts> buildRouterPortsIdentifier(String routerId) {
+ InstanceIdentifier<RouterPorts> routerInstanceIndentifier = InstanceIdentifier.builder(FloatingIpInfo.class).child
+ (RouterPorts.class, new RouterPortsKey(routerId)).build();
+ return routerInstanceIndentifier;
+ }
+
+ /* container snatint-ip-port-map {
+ list intip-port-map {
+ key router-id;
+ leaf router-id { type uint32; }
+ list ip-port {
+ key internal-ip;
+ leaf internal-ip { type string; }
+ list int-ip-proto-type {
+ key protocol;
+ leaf protocol { type protocol-types; }
+ leaf-list ports { type uint16; }
+ }
+ }
+ }
+ }
+ Method returns InternalIp port List
+ */
+
+ public static List<Integer> getInternalIpPortListInfo(DataBroker dataBroker,Long routerId, String internalIpAddress, ProtocolTypes protocolType){
+ Optional<IntIpProtoType> optionalIpProtoType = read(dataBroker, LogicalDatastoreType.CONFIGURATION, buildSnatIntIpPortIdentifier(routerId, internalIpAddress, protocolType));
+ if (optionalIpProtoType.isPresent()) {
+ return optionalIpProtoType.get().getPorts();
+ }
+ return null;
+ }
+
+ public static InstanceIdentifier<IntIpProtoType> buildSnatIntIpPortIdentifier(Long routerId, String internalIpAddress, ProtocolTypes protocolType) {
+ InstanceIdentifier<IntIpProtoType> intIpProtocolTypeId = InstanceIdentifier.builder(SnatintIpPortMap.class).child
+ (IntipPortMap.class, new IntipPortMapKey(routerId)).child(IpPort.class, new IpPortKey(internalIpAddress)).child
+ (IntIpProtoType.class, new IntIpProtoTypeKey(protocolType)).build();
+ return intIpProtocolTypeId;
+ }
+
+ public static ProtocolTypes getProtocolType(NAPTEntryEvent.Protocol protocol) {
+ ProtocolTypes protocolType = ProtocolTypes.TCP.toString().equals(protocol.toString()) ? ProtocolTypes.TCP : ProtocolTypes.UDP;
+ return protocolType;
+ }
+
+ public static NaptSwitches getNaptSwitch(DataBroker broker) {
+ Optional<NaptSwitches> switchesOptional = read(broker, LogicalDatastoreType.OPERATIONAL, getNaptSwitchesIdentifier());
+ if(switchesOptional.isPresent()) {
+ return switchesOptional.get();
+ }
+ return null;
+ }
+
+ public static InstanceIdentifier<NaptSwitches> getNaptSwitchesIdentifier() {
+ return InstanceIdentifier.create(NaptSwitches.class);
+ }
+
+ public static InstanceIdentifier<RouterToNaptSwitch> buildNaptSwitchRouterIdentifier(String routerId) {
+ return InstanceIdentifier.create(NaptSwitches.class).child(RouterToNaptSwitch.class, new RouterToNaptSwitchKey(routerId));
+ }
+
+ public static String toStringIpAddress(byte[] ipAddress, Logger log)
+ {
+ String ip = "";
+ if (ipAddress == null) {
+ return ip;
+ }
+
+ try {
+ ip = InetAddress.getByAddress(ipAddress).getHostAddress();
+ } catch(UnknownHostException e) {
+ log.error("NAT Service : Caught exception during toStringIpAddress()");
+ }
+
+ return ip;
+ }
+
+ public static String getGroupIdKey(String routerName){
+ String groupIdKey = new String("snatmiss." + routerName);
+ return groupIdKey;
+ }
+
+ public static long createGroupId(String groupIdKey,IdManagerService idManager) {
+ AllocateIdInput getIdInput = new AllocateIdInputBuilder()
+ .setPoolName(NatConstants.SNAT_IDPOOL_NAME).setIdKey(groupIdKey)
+ .build();
+ try {
+ Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
+ RpcResult<AllocateIdOutput> rpcResult = result.get();
+ return rpcResult.getResult().getIdValue();
+ } catch (NullPointerException | InterruptedException | ExecutionException e) {
+ LOG.trace("", e);
+ }
+ return 0;
+ }
+
+ public static void removePrefixFromBGP(IBgpManager bgpManager, String rd, String prefix, Logger log) {
+ try {
+ bgpManager.deletePrefix(rd, prefix);
+ } catch(Exception e) {
+ log.error("Delete prefix failed", e);
+ }
+ }
+
+ public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, BigInteger cookie, String flowId) {
+ FlowEntity flowEntity = new FlowEntity(dpnId);
+ flowEntity.setTableId(tableId);
+ flowEntity.setCookie(cookie);
+ flowEntity.setFlowId(flowId);
+ return flowEntity;
+ }
+
+ public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, String flowId) {
+ FlowEntity flowEntity = new FlowEntity(dpnId);
+ flowEntity.setTableId(tableId);
+ flowEntity.setFlowId(flowId);
+ return flowEntity;
+ }
+
+ public static IpPortMapping getIportMapping(DataBroker broker, long routerId) {
+ Optional<IpPortMapping> getIportMappingData = read(broker, LogicalDatastoreType.CONFIGURATION, getIportMappingIdentifier(routerId));
+ if(getIportMappingData.isPresent()) {
+ return getIportMappingData.get();
+ }
+ return null;
+ }
+
+ public static InstanceIdentifier<IpPortMapping> getIportMappingIdentifier(long routerId) {
+ return InstanceIdentifier.builder(IntextIpPortMap.class).child(IpPortMapping.class, new IpPortMappingKey(routerId)).build();
+ }
+
+ public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping> getIpMappingBuilder(Long routerId) {
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping> idBuilder = InstanceIdentifier.builder(IntextIpMap.class)
+ .child(org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping.class, new org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMappingKey(routerId)).build();
+ return idBuilder;
+ }
+
+ public static List<String> getExternalIpsForRouter(DataBroker dataBroker,Long routerId) {
+ Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping> ipMappingOptional = read(dataBroker,
+ LogicalDatastoreType.OPERATIONAL, getIpMappingBuilder(routerId));
+ List<String> externalIps = new ArrayList<>();
+ if (ipMappingOptional.isPresent()) {
+ List<IpMap> ipMaps = ipMappingOptional.get().getIpMap();
+ for (IpMap ipMap : ipMaps) {
+ externalIps.add(ipMap.getExternalIp());
+ }
+ return externalIps;
+ }
+ return null;
+ }
+
+ /*
+ container external-ips-counter {
+ config false;
+ list external-counters{
+ key segment-id;
+ leaf segment-id { type uint32; }
+ list external-ip-counter {
+ key external-ip;
+ leaf external-ip { type string; }
+ leaf counter { type uint8; }
+ }
+ }
+ }
+ */
+
+ public static String getLeastLoadedExternalIp(DataBroker dataBroker, long segmentId){
+ String leastLoadedExternalIp = null;
+ InstanceIdentifier<ExternalCounters> id = InstanceIdentifier.builder(ExternalIpsCounter.class).child(ExternalCounters.class, new ExternalCountersKey(segmentId)).build();
+ Optional <ExternalCounters> externalCountersData = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
+ if (externalCountersData.isPresent()) {
+ ExternalCounters externalCounter = externalCountersData.get();
+ List<ExternalIpCounter> externalIpCounterList = externalCounter.getExternalIpCounter();
+ short countOfLstLoadExtIp = 32767;
+ for(ExternalIpCounter externalIpCounter : externalIpCounterList){
+ String curExternalIp = externalIpCounter.getExternalIp();
+ short countOfCurExtIp = externalIpCounter.getCounter();
+ if( countOfCurExtIp < countOfLstLoadExtIp ){
+ countOfLstLoadExtIp = countOfCurExtIp;
+ leastLoadedExternalIp = curExternalIp;
+ }
+ }
+ }
+ return leastLoadedExternalIp;
+ }
+
+ public static String[] getSubnetIpAndPrefix(DataBroker dataBroker, Uuid subnetId){
+ String subnetIP = getSubnetIp(dataBroker, subnetId);
+ if(subnetId != null){
+ return getSubnetIpAndPrefix(subnetIP);
+ }
+ return null;
+ }
+
+ public static String getSubnetIp(DataBroker dataBroker, Uuid subnetId){
+ InstanceIdentifier<Subnetmap> subnetmapId = InstanceIdentifier
+ .builder(Subnetmaps.class)
+ .child(Subnetmap.class, new SubnetmapKey(subnetId))
+ .build();
+ Optional<Subnetmap> removedSubnet = read(dataBroker, LogicalDatastoreType.CONFIGURATION, subnetmapId);
+ if(removedSubnet.isPresent()) {
+ Subnetmap subnetMapEntry = removedSubnet.get();
+ return subnetMapEntry.getSubnetIp();
+ }
+ return null;
+
+ }
+ public static String[] getSubnetIpAndPrefix(String subnetString){
+ String[] subnetSplit = subnetString.split("/");
+ String subnetIp = subnetSplit[0];
+ String subnetPrefix = "0";
+ if (subnetSplit.length == 2) {
+ subnetPrefix = subnetSplit[1];
+ }
+ return new String[] {subnetIp, subnetPrefix};
+ }
+
+ public static String[] getExternalIpAndPrefix(String leastLoadedExtIpAddr){
+ String[] leastLoadedExtIpAddrSplit = leastLoadedExtIpAddr.split("/");
+ String leastLoadedExtIp = leastLoadedExtIpAddrSplit[0];
+ String leastLoadedExtIpPrefix = String.valueOf(NatConstants.DEFAULT_PREFIX);
+ if (leastLoadedExtIpAddrSplit.length == 2) {
+ leastLoadedExtIpPrefix = leastLoadedExtIpAddrSplit[1];
+ }
+ return new String[] {leastLoadedExtIp, leastLoadedExtIpPrefix};
+ }
+
+ public static List<BigInteger> getDpnsForRouter(DataBroker dataBroker, String routerUuid){
+ InstanceIdentifier id = InstanceIdentifier.builder(NeutronRouterDpns.class).child(RouterDpnList.class, new RouterDpnListKey(routerUuid)).build();
+ Optional<RouterDpnList> routerDpnListData = read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+ List<BigInteger> dpns = new ArrayList<>();
+ if (routerDpnListData.isPresent()) {
+ List<DpnVpninterfacesList> dpnVpninterfacesList = routerDpnListData.get().getDpnVpninterfacesList();
+ for (DpnVpninterfacesList dpnVpnInterface : dpnVpninterfacesList) {
+ dpns.add(dpnVpnInterface.getDpnId());
+ }
+ return dpns;
+ }
+ return null;
+ }
+
+ public static long getBgpVpnId(DataBroker dataBroker, String routerName){
+ long bgpVpnId = NatConstants.INVALID_ID;
+ Uuid bgpVpnUuid = NatUtil.getVpnForRouter(dataBroker, routerName);
+ if(bgpVpnUuid != null){
+ bgpVpnId = NatUtil.getVpnId(dataBroker, bgpVpnUuid.getValue());
+ }
+ return bgpVpnId;
+ }
+}
--- /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.natservice.internal;
+
+import java.math.BigInteger;
+import java.util.List;
+
+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.mdsalutil.*;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.ext.routers.Routers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.NeutronRouterDpns;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class RouterDpnChangeListener extends AbstractDataChangeListener<DpnVpninterfacesList> implements AutoCloseable{
+ private static final Logger LOG = LoggerFactory.getLogger(RouterDpnChangeListener.class);
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker dataBroker;
+ private SNATDefaultRouteProgrammer defaultRouteProgrammer;
+ private NaptSwitchHA naptSwitchHA;
+ private IMdsalApiManager mdsalManager;
+ private IdManagerService idManager;
+
+ public RouterDpnChangeListener (final DataBroker db) {
+ super(DpnVpninterfacesList.class);
+ dataBroker = db;
+ registerListener(db);
+ }
+
+ void setDefaultProgrammer(SNATDefaultRouteProgrammer defaultRouteProgrammer) {
+ this.defaultRouteProgrammer = defaultRouteProgrammer;
+ }
+
+ void setNaptSwitchHA(NaptSwitchHA switchHA) {
+ naptSwitchHA = switchHA;
+ }
+
+ void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ public void setIdManager(IdManagerService idManager) {
+ this.idManager = idManager;
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("Router ports Listener Closed");
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ getWildCardPath(), RouterDpnChangeListener.this, AsyncDataBroker.DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("RouterPorts DataChange listener registration fail!", e);
+ throw new IllegalStateException("RouterPorts Listener registration Listener failed.", e);
+ }
+ }
+
+ private InstanceIdentifier<DpnVpninterfacesList> getWildCardPath() {
+ return InstanceIdentifier.create(NeutronRouterDpns.class).child(RouterDpnList.class).child(DpnVpninterfacesList.class);
+ }
+
+ @Override
+ protected void add(final InstanceIdentifier<DpnVpninterfacesList> identifier, final DpnVpninterfacesList dpnInfo) {
+ LOG.trace("Add event - key: {}, value: {}", identifier, dpnInfo);
+ final String routerId = identifier.firstKeyOf(RouterDpnList.class).getRouterId();
+ BigInteger dpnId = dpnInfo.getDpnId();
+ //check router is associated to external network
+ InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerId);
+ Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+ if (routerData.isPresent()) {
+ Uuid networkId = routerData.get().getNetworkId();
+ if(networkId != null) {
+ LOG.debug("Router {} is associated with ext nw {}", routerId, networkId);
+ Uuid vpnName = NatUtil.getVpnForRouter(dataBroker,routerId);
+ Long vpnId;
+ if (vpnName == null) {
+ LOG.debug("Internal vpn associated to router {}",routerId);
+ vpnId = NatUtil.getVpnId(dataBroker,routerId);
+ if (vpnId == NatConstants.INVALID_ID) {
+ LOG.error("Invalid vpnId returned for routerName {}",routerId);
+ return;
+ }
+ LOG.debug("Retrieved vpnId {} for router {}",vpnId,routerId);
+ //Install default entry in FIB to SNAT table
+ LOG.debug("Installing default route in FIB on dpn {} for router {} with vpn {}...", dpnId,routerId,vpnId);
+ defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId);
+ } else {
+ LOG.debug("External BGP vpn associated to router {}",routerId);
+ vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
+ if (vpnId == NatConstants.INVALID_ID) {
+ LOG.error("Invalid vpnId returned for routerName {}", routerId);
+ return;
+ }
+ Long routId = NatUtil.getVpnId(dataBroker, routerId);
+ if (routId == NatConstants.INVALID_ID) {
+ LOG.error("Invalid routId returned for routerName {}",routerId);
+ return;
+ }
+ LOG.debug("Retrieved vpnId {} for router {}",vpnId,routerId);
+ //Install default entry in FIB to SNAT table
+ LOG.debug("Installing default route in FIB on dpn {} for routerId {} with vpnId {}...", dpnId,routerId,vpnId);
+ defaultRouteProgrammer.installDefNATRouteInDPN(dpnId, vpnId, routId);
+ }
+
+ if (routerData.get().isEnableSnat()) {
+ LOG.info("SNAT enabled for router {}", routerId);
+ handleSNATForDPN(dpnId, routerId ,vpnId);
+ } else {
+ LOG.info("SNAT is not enabled for router {} to handle addDPN event {}", routerId, dpnId);
+ }
+ }
+ } else {
+ LOG.debug("Router {} is not associated with External network", routerId);
+ }
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<DpnVpninterfacesList> identifier, DpnVpninterfacesList dpnInfo) {
+ LOG.trace("Remove event - key: {}, value: {}", identifier, dpnInfo);
+ final String routerId = identifier.firstKeyOf(RouterDpnList.class).getRouterId();
+ BigInteger dpnId = dpnInfo.getDpnId();
+ //check router is associated to external network
+ InstanceIdentifier<Routers> id = NatUtil.buildRouterIdentifier(routerId);
+ Optional<Routers> routerData = NatUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+ if (routerData.isPresent()) {
+ Uuid networkId = routerData.get().getNetworkId();
+ if (networkId != null) {
+ LOG.debug("Router {} is associated with ext nw {}", routerId, networkId);
+ Uuid vpnName = NatUtil.getVpnForRouter(dataBroker, routerId);
+ Long vpnId;
+ if (vpnName == null) {
+ LOG.debug("Internal vpn associated to router {}", routerId);
+ vpnId = NatUtil.getVpnId(dataBroker, routerId);
+ if (vpnId == NatConstants.INVALID_ID) {
+ LOG.error("Invalid vpnId returned for routerName {}", routerId);
+ return;
+ }
+ LOG.debug("Retrieved vpnId {} for router {}",vpnId,routerId);
+ //Remove default entry in FIB
+ LOG.debug("Removing default route in FIB on dpn {} for vpn {} ...", dpnId, vpnName);
+ defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId, vpnId);
+ } else {
+ LOG.debug("External vpn associated to router {}", routerId);
+ vpnId = NatUtil.getVpnId(dataBroker, vpnName.getValue());
+ if (vpnId == NatConstants.INVALID_ID) {
+ LOG.error("Invalid vpnId returned for routerName {}", routerId);
+ return;
+ }
+ Long routId = NatUtil.getVpnId(dataBroker, routerId);
+ if (routId == NatConstants.INVALID_ID) {
+ LOG.error("Invalid routId returned for routerName {}",routerId);
+ return;
+ }
+ LOG.debug("Retrieved vpnId {} for router {}",vpnId,routerId);
+ //Remove default entry in FIB
+ LOG.debug("Removing default route in FIB on dpn {} for vpn {} ...", dpnId, vpnName);
+ defaultRouteProgrammer.removeDefNATRouteInDPN(dpnId,vpnId,routId);
+ }
+
+ if (routerData.get().isEnableSnat()) {
+ LOG.info("SNAT enabled for router {}", routerId);
+ removeSNATFromDPN(dpnId, routerId, vpnId);
+ } else {
+ LOG.info("SNAT is not enabled for router {} to handle removeDPN event {}", routerId, dpnId);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<DpnVpninterfacesList> identifier, DpnVpninterfacesList original, DpnVpninterfacesList update) {
+ LOG.trace("Update event - key: {}, original: {}, update: {}", identifier, original, update);
+ }
+ void handleSNATForDPN(BigInteger dpnId, String routerName,Long routerVpnId) {
+ //Check if primary and secondary switch are selected, If not select the role
+ //Install select group to NAPT switch
+ //Install default miss entry to NAPT switch
+ BigInteger naptSwitch;
+ try {
+ Long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ if (routerId == NatConstants.INVALID_ID) {
+ LOG.error("Invalid routerId returned for routerName {}", routerName);
+ return;
+ }
+ BigInteger naptId = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
+ if (naptId == null || naptId.equals(BigInteger.ZERO)) {
+ LOG.debug("No NaptSwitch is selected for router {}", routerName);
+
+ naptSwitch = dpnId;
+ boolean naptstatus = naptSwitchHA.updateNaptSwitch(routerName, naptSwitch);
+ if (!naptstatus) {
+ LOG.error("Failed to update newNaptSwitch {} for routername {}", naptSwitch, routerName);
+ return;
+ }
+ LOG.debug("Switch {} is elected as NaptSwitch for router {}", dpnId, routerName);
+
+ //installing group
+ List<BucketInfo> bucketInfo = naptSwitchHA.handleGroupInPrimarySwitch();
+ naptSwitchHA.installSnatGroupEntry(naptSwitch, bucketInfo, routerName);
+
+ naptSwitchHA.installSnatFlows(routerName, routerId, naptSwitch, routerVpnId);
+
+ } else {
+ LOG.debug("Napt switch with Id {} is already elected for router {}", naptId, routerName);
+ naptSwitch = naptId;
+
+ //installing group
+ List<BucketInfo> bucketInfo = naptSwitchHA.handleGroupInNeighborSwitches(dpnId, routerName, naptSwitch);
+ if (bucketInfo == null) {
+ LOG.debug("Failed to populate bucketInfo for dpnId {} routername {} naptSwitch {}", dpnId, routerName,
+ naptSwitch);
+ return;
+ }
+ naptSwitchHA.installSnatGroupEntry(dpnId, bucketInfo, routerName);
+ }
+ // Install miss entry (table 26) pointing to group
+ long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
+ FlowEntity flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId, routerVpnId, NatConstants.ADD_FLOW);
+ if (flowEntity == null) {
+ LOG.debug("Failed to populate flowentity for router {} with dpnId {} groupId {}", routerName, dpnId, groupId);
+ return;
+ }
+ LOG.debug("Successfully installed flow for dpnId {} router {} group {}", dpnId, routerName, groupId);
+ mdsalManager.installFlow(flowEntity);
+ } catch (Exception ex) {
+ LOG.error("Exception in handleSNATForDPN method : {}", ex);
+ }
+ }
+
+ void removeSNATFromDPN(BigInteger dpnId, String routerName, long routerVpnId) {
+ //irrespective of naptswitch or non-naptswitch, SNAT default miss entry need to be removed
+ //remove miss entry to NAPT switch
+ //if naptswitch elect new switch and install Snat flows and remove those flows in oldnaptswitch
+
+ Long routerId = NatUtil.getVpnId(dataBroker, routerName);
+ if (routerId == NatConstants.INVALID_ID) {
+ LOG.error("Invalid routerId returned for routerName {}",routerName);
+ return;
+ }
+ BigInteger naptSwitch = NatUtil.getPrimaryNaptfromRouterId(dataBroker, routerId);
+ if (naptSwitch == null || naptSwitch.equals(BigInteger.ZERO)) {
+ LOG.debug("No naptSwitch is selected for router {}", routerName);
+ return;
+ }
+ try {
+ boolean naptStatus = naptSwitchHA.isNaptSwitchDown(routerName,dpnId,naptSwitch,routerVpnId);
+ if (!naptStatus) {
+ LOG.debug("NaptSwitchDown: Switch with DpnId {} is not naptSwitch for router {}",
+ dpnId, routerName);
+ } else {
+ naptSwitchHA.removeSnatFlowsInOldNaptSwitch(routerName, naptSwitch);
+ }
+ } catch (Exception ex) {
+ LOG.debug("Exception while handling naptSwitch down for router {} : {}",routerName,ex);
+ }
+
+ long groupId = NatUtil.createGroupId(NatUtil.getGroupIdKey(routerName), idManager);
+ FlowEntity flowEntity = null;
+ try {
+ flowEntity = naptSwitchHA.buildSnatFlowEntity(dpnId, routerName, groupId, routerVpnId, NatConstants.DEL_FLOW);
+ if (flowEntity == null) {
+ LOG.debug("Failed to populate flowentity for router {} with dpnId {} groupIs {}",routerName,dpnId,groupId);
+ return;
+ }
+ LOG.debug("NAT Service : Removing default SNAT miss entry flow entity {}",flowEntity);
+ mdsalManager.removeFlow(flowEntity);
+
+ } catch (Exception ex) {
+ LOG.debug("NAT Service : Failed to remove default SNAT miss entry flow entity {} : {}",flowEntity,ex);
+ return;
+ }
+ LOG.debug("NAT Service : Removed default SNAT miss entry flow for dpnID {} with routername {}", dpnId, routerName);
+
+ //remove group
+ GroupEntity groupEntity = null;
+ try {
+ groupEntity = MDSALUtil.buildGroupEntity(dpnId, groupId, routerName,
+ GroupTypes.GroupAll, null);
+ LOG.info("NAT Service : Removing NAPT GroupEntity:{}", groupEntity);
+ mdsalManager.removeGroup(groupEntity);
+ } catch (Exception ex) {
+ LOG.debug("NAT Service : Failed to remove group entity {} : {}",groupEntity,ex);
+ return;
+ }
+ LOG.debug("NAT Service : Removed default SNAT miss entry flow for dpnID {} with routerName {}", dpnId, routerName);
+ }
+}
--- /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.natservice.internal;
+
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+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.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.FloatingIpInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.RouterPorts;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.RouterPortsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.RouterPortsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.PortsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.PortsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.router.to.vpn.mapping.Routermapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.router.to.vpn.mapping.RoutermappingBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.router.to.vpn.mapping.RoutermappingKey;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class RouterPortsListener extends AbstractDataChangeListener<RouterPorts> implements AutoCloseable{
+ private static final Logger LOG = LoggerFactory.getLogger(RouterPortsListener.class);
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+
+
+ public RouterPortsListener (final DataBroker db) {
+ super(RouterPorts.class);
+ broker = db;
+ registerListener(db);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("Router ports Listener Closed");
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ getWildCardPath(), RouterPortsListener.this, AsyncDataBroker.DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("RouterPorts DataChange listener registration fail!", e);
+ throw new IllegalStateException("RouterPorts Listener registration Listener failed.", e);
+ }
+ }
+
+ private InstanceIdentifier<RouterPorts> getWildCardPath() {
+ return InstanceIdentifier.create(FloatingIpInfo.class).child(RouterPorts.class);
+ }
+
+
+ @Override
+ protected void add(final InstanceIdentifier<RouterPorts> identifier, final RouterPorts routerPorts) {
+ LOG.trace("Add router ports method - key: " + identifier + ", value=" + routerPorts );
+ Optional<RouterPorts> optRouterPorts = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
+ if(optRouterPorts.isPresent()) {
+ RouterPorts ports = optRouterPorts.get();
+ String routerName = ports.getRouterId();
+ MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier,
+ new RouterPortsBuilder().setKey(new RouterPortsKey(routerName)).setRouterId(routerName)
+ .setExternalNetworkId(routerPorts.getExternalNetworkId()).build());
+ } else {
+ String routerName = routerPorts.getRouterId();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, identifier,
+ new RouterPortsBuilder().setKey(new RouterPortsKey(routerName)).setRouterId(routerName)
+ .setExternalNetworkId(routerPorts.getExternalNetworkId()).build());
+ }
+ //Check if the router is associated with any BGP VPN and update the association
+ String routerName = routerPorts.getRouterId();
+ Uuid vpnName = NatUtil.getVpnForRouter(broker, routerName);
+ if(vpnName != null) {
+ InstanceIdentifier<Routermapping> routerMappingId = NatUtil.getRouterVpnMappingId(routerName);
+ Optional<Routermapping> optRouterMapping = NatUtil.read(broker, LogicalDatastoreType.OPERATIONAL, routerMappingId);
+ if(!optRouterMapping.isPresent()){
+ Long vpnId = NatUtil.getVpnId(broker, vpnName.getValue());
+ LOG.debug("Updating router {} to VPN {} association with Id {}", routerName, vpnName, vpnId);
+ Routermapping routerMapping = new RoutermappingBuilder().setKey(new RoutermappingKey(routerName))
+ .setRouterName(routerName).setVpnName(vpnName.getValue()).setVpnId(vpnId).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, routerMappingId, routerMapping);
+ }
+ }
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<RouterPorts> identifier, RouterPorts routerPorts) {
+ LOG.trace("Remove router ports method - key: " + identifier + ", value=" + routerPorts );
+ //MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, identifier);
+ //Remove the router to vpn association mapping entry if at all present
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, NatUtil.getRouterVpnMappingId(routerPorts.getRouterId()));
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<RouterPorts> identifier, RouterPorts original, RouterPorts update) {
+ LOG.trace("Update router ports method - key: " + identifier + ", original=" + original + ", update=" + update );
+ }
+}
--- /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.natservice.internal;
+
+import java.math.BigInteger;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+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.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+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.OdlInterfaceRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.RouterPorts;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.Ports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.ports.IpMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMappingKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.NeutronvpnListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.RouterAssociatedToVpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.RouterDisassociatedFromVpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.SubnetAddedToVpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.SubnetDeletedFromVpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.PortAddedToSubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.PortRemovedFromSubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.SubnetUpdatedInVpn;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+public class RouterToVpnListener implements NeutronvpnListener {
+ private static final Logger LOG = LoggerFactory.getLogger(RouterToVpnListener.class);
+ private DataBroker dataBroker;
+ private FloatingIPListener floatingIpListener;
+ private OdlInterfaceRpcService interfaceManager;
+
+
+ private ExternalRoutersListener externalRoutersListener;
+
+ public RouterToVpnListener(DataBroker db) {
+ dataBroker = db;
+ }
+
+ void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
+ this.interfaceManager = interfaceManager;
+ }
+
+ void setFloatingIpListener(FloatingIPListener floatingIpListener) {
+ this.floatingIpListener = floatingIpListener;
+ }
+
+ void setExternalRoutersListener(ExternalRoutersListener externalRoutersListener) {
+ this.externalRoutersListener = externalRoutersListener;
+ }
+
+ /**
+ * router association to vpn
+ *
+ */
+ @Override
+ public void onRouterAssociatedToVpn(RouterAssociatedToVpn notification) {
+ String routerName = notification.getRouterId().getValue();
+ String vpnName = notification.getVpnId().getValue();
+ //check router is associated to external network
+ String extNetwork = NatUtil.getAssociatedExternalNetwork(dataBroker, routerName);
+ if(extNetwork != null) {
+ LOG.debug("Router {} is associated with ext nw {}", routerName, extNetwork);
+ handleDNATConfigurationForRouterAssociation(routerName, vpnName, extNetwork);
+ externalRoutersListener.changeLocalVpnIdToBgpVpnId(routerName, vpnName);
+ } else {
+ LOG.debug("Ignoring the Router {} association with VPN {} since it is not external router", routerName);
+ }
+
+ }
+
+ /**
+ * router disassociation from vpn
+ *
+ */
+ @Override
+ public void onRouterDisassociatedFromVpn(RouterDisassociatedFromVpn notification) {
+ String routerName = notification.getRouterId().getValue();
+ String vpnName = notification.getVpnId().getValue();
+ //check router is associated to external network
+ String extNetwork = NatUtil.getAssociatedExternalNetwork(dataBroker, routerName);
+ if(extNetwork != null) {
+ LOG.debug("Router {} is associated with ext nw {}", routerName, extNetwork);
+ handleDNATConfigurationForRouterDisassociation(routerName, vpnName, extNetwork);
+ externalRoutersListener.changeBgpVpnIdToLocalVpnId(routerName, vpnName);
+ } else {
+ LOG.debug("Ignoring the Router {} association with VPN {} since it is not external router", routerName);
+ }
+ }
+
+ void handleDNATConfigurationForRouterAssociation(String routerName, String vpnName, String externalNetwork) {
+ InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
+ Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);
+ if(!optRouterPorts.isPresent()) {
+ LOG.debug("Could not read Router Ports data object with id: {} to handle associate vpn {}", routerName, vpnName);
+ return;
+ }
+ Uuid networkId = Uuid.getDefaultInstance(externalNetwork);
+ RouterPorts routerPorts = optRouterPorts.get();
+ List<Ports> interfaces = routerPorts.getPorts();
+ Map<String, BigInteger> portToDpnMap = new HashMap<>();
+ for(Ports port : interfaces) {
+ String portName = port.getPortName();
+ BigInteger dpnId = getDpnForInterface(interfaceManager, portName);
+ if(dpnId.equals(BigInteger.ZERO)) {
+ LOG.debug("DPN not found for {}, skip handling of router {} association with vpn", portName, routerName, vpnName);
+ continue;
+ }
+ portToDpnMap.put(portName, dpnId);
+ List<IpMapping> ipMapping = port.getIpMapping();
+ for(IpMapping ipMap : ipMapping) {
+ String externalIp = ipMap.getExternalIp();
+ //remove all NAT related entries with routerName
+ //floatingIpListener.removeNATOnlyFlowEntries(dpnId, portName, routerName, null, ipMap.getInternalIp(), externalIp);
+ //Create NAT entries with VPN Id
+ LOG.debug("Updating DNAT flows with VPN metadata {} ", vpnName);
+ floatingIpListener.createNATOnlyFlowEntries(dpnId, portName, routerName, vpnName, networkId, ipMap.getInternalIp(), externalIp);
+ }
+ }
+ }
+
+ void handleDNATConfigurationForRouterDisassociation(String routerName, String vpnName, String externalNetwork) {
+ InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
+ Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);
+ if(!optRouterPorts.isPresent()) {
+ LOG.debug("Could not read Router Ports data object with id: {} to handle disassociate vpn {}", routerName, vpnName);
+ return;
+ }
+ Uuid networkId = Uuid.getDefaultInstance(externalNetwork);
+ RouterPorts routerPorts = optRouterPorts.get();
+ List<Ports> interfaces = routerPorts.getPorts();
+ for(Ports port : interfaces) {
+ String portName = port.getPortName();
+ BigInteger dpnId = getDpnForInterface(interfaceManager, portName);
+ if(dpnId.equals(BigInteger.ZERO)) {
+ LOG.debug("DPN not found for {}, skip handling of router {} association with vpn", portName, routerName, vpnName);
+ continue;
+ }
+ List<IpMapping> ipMapping = port.getIpMapping();
+ for(IpMapping ipMap : ipMapping) {
+ String externalIp = ipMap.getExternalIp();
+ //remove all NAT related entries with routerName
+ //floatingIpListener.removeNATOnlyFlowEntries(dpnId, portName, routerName, vpnName, ipMap.getInternalIp(), externalIp);
+ //Create NAT entries with VPN Id
+ floatingIpListener.createNATOnlyFlowEntries(dpnId, portName, routerName, null, networkId, ipMap.getInternalIp(), externalIp);
+ }
+ }
+ }
+
+ private BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
+ BigInteger nodeId = BigInteger.ZERO;
+ try {
+ GetDpidFromInterfaceInput
+ dpIdInput =
+ new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
+ Future<RpcResult<GetDpidFromInterfaceOutput>>
+ dpIdOutput =
+ interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
+ RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
+ if (dpIdResult.isSuccessful()) {
+ nodeId = dpIdResult.getResult().getDpid();
+ } else {
+ LOG.error("Could not retrieve DPN Id for interface {}", ifName);
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Exception when getting dpn for interface {}", ifName, e);
+ }
+ return nodeId;
+ }
+
+ @Override
+ public void onSubnetAddedToVpn(SubnetAddedToVpn notification) {
+ throw new RuntimeException("Unsupported notification");
+ }
+
+ @Override
+ public void onSubnetDeletedFromVpn(SubnetDeletedFromVpn notification) {
+ throw new RuntimeException("Unsupported notification");
+ }
+
+ @Override
+ public void onPortAddedToSubnet(PortAddedToSubnet notification) {
+ throw new RuntimeException("Unsupported notification");
+ }
+
+ @Override
+ public void onPortRemovedFromSubnet(PortRemovedFromSubnet notification) {
+ throw new RuntimeException("Unsupported notification");
+ }
+
+ @Override
+ public void onSubnetUpdatedInVpn(SubnetUpdatedInVpn notification) {
+ throw new RuntimeException("Unsupported notification");
+ }
+
+}
--- /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.natservice.internal;
+
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
+import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
+import org.opendaylight.vpnservice.mdsalutil.InstructionType;
+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.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SNATDefaultRouteProgrammer {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SNATDefaultRouteProgrammer.class);
+ private IMdsalApiManager mdsalManager;
+
+ public SNATDefaultRouteProgrammer(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ private FlowEntity buildDefNATFlowEntity(BigInteger dpId, long vpnId) {
+
+ InetAddress defaultIP = null;
+
+ try {
+ defaultIP = InetAddress.getByName("0.0.0.0");
+
+ } catch (UnknownHostException e) {
+ LOG.error("UnknowHostException in buildDefNATFlowEntity. Failed to build FIB Table Flow for Default Route to NAT table ");
+ return null;
+ }
+
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+
+ //add match for default route "0.0.0.0/0"
+// matches.add(new MatchInfo(MatchFieldType.ipv4_dst, new long[] {
+// NatUtil.getIpAddress(defaultIP.getAddress()), 0 }));
+
+ //add match for vrfid
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
+
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.PSNAT_TABLE }));
+
+ String flowRef = getFlowRefFib(dpId, NatConstants.L3_FIB_TABLE, vpnId);
+
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.L3_FIB_TABLE, flowRef,
+ NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_DNAT_TABLE, matches, instructions);
+
+ return flowEntity;
+
+
+ }
+
+ private FlowEntity buildDefNATFlowEntity(BigInteger dpId, long bgpVpnId, long routerId) {
+
+ InetAddress defaultIP = null;
+
+ try {
+ defaultIP = InetAddress.getByName("0.0.0.0");
+
+ } catch (UnknownHostException e) {
+ LOG.error("UnknowHostException in buildDefNATFlowEntity. Failed to build FIB Table Flow for Default Route to NAT table ");
+ return null;
+ }
+
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+
+ //add match for default route "0.0.0.0/0"
+// matches.add(new MatchInfo(MatchFieldType.ipv4_dst, new long[] {
+// NatUtil.getIpAddress(defaultIP.getAddress()), 0 }));
+
+ //add match for vrfid
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ BigInteger.valueOf(bgpVpnId), MetaDataUtil.METADATA_MASK_VRFID }));
+
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.PSNAT_TABLE }));
+
+ String flowRef = getFlowRefFib(dpId, NatConstants.L3_FIB_TABLE, routerId);
+
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NatConstants.L3_FIB_TABLE, flowRef,
+ NatConstants.DEFAULT_DNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ NatConstants.COOKIE_DNAT_TABLE, matches, instructions);
+
+ return flowEntity;
+
+
+ }
+
+ private String getFlowRefFib(BigInteger dpnId, short tableId, long routerID) {
+ return new StringBuilder().append(NatConstants.NAPT_FLOWID_PREFIX).append(dpnId).append(NatConstants.FLOWID_SEPARATOR).
+ append(tableId).append(NatConstants.FLOWID_SEPARATOR).append(routerID).toString();
+ }
+
+ void installDefNATRouteInDPN(BigInteger dpnId, long vpnId) {
+ FlowEntity flowEntity = buildDefNATFlowEntity(dpnId, vpnId);
+ if(flowEntity == null) {
+ LOG.error("Flow entity received is NULL. Cannot proceed with installation of Default NAT flow");
+ return;
+ }
+ mdsalManager.installFlow(flowEntity);
+ }
+
+ void installDefNATRouteInDPN(BigInteger dpnId, long bgpVpnId, long routerId) {
+ FlowEntity flowEntity = buildDefNATFlowEntity(dpnId, bgpVpnId, routerId);
+ if(flowEntity == null) {
+ LOG.error("Flow entity received is NULL. Cannot proceed with installation of Default NAT flow");
+ return;
+ }
+ mdsalManager.installFlow(flowEntity);
+ }
+
+ void removeDefNATRouteInDPN(BigInteger dpnId, long vpnId) {
+ FlowEntity flowEntity = buildDefNATFlowEntity(dpnId, vpnId);
+ if(flowEntity == null) {
+ LOG.error("Flow entity received is NULL. Cannot proceed with installation of Default NAT flow");
+ return;
+ }
+ mdsalManager.removeFlow(flowEntity);
+ }
+
+ void removeDefNATRouteInDPN(BigInteger dpnId, long bgpVpnId, long routerId) {
+ FlowEntity flowEntity = buildDefNATFlowEntity(dpnId, bgpVpnId, routerId);
+ if(flowEntity == null) {
+ LOG.error("Flow entity received is NULL. Cannot proceed with installation of Default NAT flow");
+ return;
+ }
+ mdsalManager.removeFlow(flowEntity);
+ }
+
+}
--- /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.natservice.internal;
+
+public class SessionAddress {
+
+ private String ipAddress;
+ private int portNumber;
+
+ public SessionAddress(String ipAddress, int portNumber) {
+ this.ipAddress = ipAddress;
+ this.portNumber = portNumber;
+ }
+ public String getIpAddress() {
+ return ipAddress;
+ }
+ public int getPortNumber() {
+ return portNumber;
+ }
+
+}
--- /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.natservice.internal;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.concurrent.Future;
+import java.util.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.bgpmanager.api.IBgpManager;
+import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.ActionType;
+import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
+import org.opendaylight.vpnservice.mdsalutil.InstructionType;
+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.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.CreateFibEntryInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.CreateFibEntryInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.RemoveFibEntryInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.RemoveFibEntryInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fib.rpc.rev160121.FibRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.VpnRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.GenerateVpnLabelInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.GenerateVpnLabelInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.GenerateVpnLabelOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.RemoveVpnLabelInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.vpn.rpc.rev160201.RemoveVpnLabelInputBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import com.google.common.util.concurrent.ListenableFuture;
+
+public class VpnFloatingIpHandler implements FloatingIPHandler {
+ private static final Logger LOG = LoggerFactory.getLogger(VpnFloatingIpHandler.class);
+ private VpnRpcService vpnService;
+ private FibRpcService fibService;
+ private IBgpManager bgpManager;
+ private DataBroker dataBroker;
+ private IMdsalApiManager mdsalManager;
+ private FloatingIPListener listener;
+
+ static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
+ static final String FLOWID_PREFIX = "NAT.";
+ static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000002", 16);
+
+ public VpnFloatingIpHandler(VpnRpcService vpnService, IBgpManager bgpManager, FibRpcService fibService) {
+ this.vpnService = vpnService;
+ this.fibService = fibService;
+ this.bgpManager = bgpManager;
+ }
+
+ void setListener(FloatingIPListener listener) {
+ this.listener = listener;
+ }
+
+ void setBroker(DataBroker broker) {
+ dataBroker = broker;
+ }
+
+ void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ @Override
+ public void onAddFloatingIp(final BigInteger dpnId, final String routerId,
+ Uuid networkId, final String interfaceName, final String externalIp, final String internalIp) {
+ final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
+ if(vpnName == null) {
+ LOG.info("No VPN associated with ext nw {} to handle add floating ip configuration {} in router {}",
+ networkId, externalIp, routerId);
+ return;
+ }
+
+ GenerateVpnLabelInput labelInput = new GenerateVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
+ Future<RpcResult<GenerateVpnLabelOutput>> labelFuture = vpnService.generateVpnLabel(labelInput);
+
+ ListenableFuture<RpcResult<Void>> future = Futures.transform(JdkFutureAdapters.listenInPoolThread(labelFuture), new AsyncFunction<RpcResult<GenerateVpnLabelOutput>, RpcResult<Void>>() {
+
+ @Override
+ public ListenableFuture<RpcResult<Void>> apply(RpcResult<GenerateVpnLabelOutput> result) throws Exception {
+ if(result.isSuccessful()) {
+ GenerateVpnLabelOutput output = result.getResult();
+ long label = output.getLabel();
+ LOG.debug("Generated label {} for prefix {}", label, externalIp);
+ listener.updateOperationalDS(routerId, interfaceName, (int)label, internalIp, externalIp);
+
+ //Inform BGP
+ String rd = NatUtil.getVpnRd(dataBroker, vpnName);
+ String nextHopIp = NatUtil.getEndpointIpAddressForDPN(dataBroker, dpnId);
+ LOG.debug("Nexthop ip for prefix {} is {}", externalIp, nextHopIp);
+ NatUtil.addPrefixToBGP(bgpManager, rd, externalIp + "/32", nextHopIp, label, LOG);
+
+ List<Instruction> instructions = new ArrayList<Instruction>();
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+ actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[] { Integer.toString(NatConstants.PDNAT_TABLE) }));
+ instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos).buildInstruction(0));
+ makeTunnelTableEntry(dpnId, label, instructions);
+
+ //Install custom FIB routes
+ List<Instruction> customInstructions = new ArrayList<>();
+ customInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NatConstants.PDNAT_TABLE }).buildInstruction(0));
+ makeLFibTableEntry(dpnId, label, NatConstants.PDNAT_TABLE);
+ CreateFibEntryInput input = new CreateFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setInstruction(customInstructions)
+ .setIpAddress(externalIp + "/32").setServiceId(label).setInstruction(customInstructions).build();
+ //Future<RpcResult<java.lang.Void>> createFibEntry(CreateFibEntryInput input);
+ Future<RpcResult<Void>> future = fibService.createFibEntry(input);
+ return JdkFutureAdapters.listenInPoolThread(future);
+ } else {
+ String errMsg = String.format("Could not retrieve the label for prefix %s in VPN %s, %s", externalIp, vpnName, result.getErrors());
+ LOG.error(errMsg);
+ return Futures.immediateFailedFuture(new RuntimeException(errMsg));
+ }
+ }
+ });
+
+ Futures.addCallback(future, new FutureCallback<RpcResult<Void>>() {
+
+ @Override
+ public void onFailure(Throwable error) {
+ LOG.error("Error in generate label or fib install process", error);
+ }
+
+ @Override
+ public void onSuccess(RpcResult<Void> result) {
+ if(result.isSuccessful()) {
+ LOG.info("Successfully installed custom FIB routes for prefix {}", externalIp);
+ } else {
+ LOG.error("Error in rpc call to create custom Fib entries for prefix {} in DPN {}, {}", externalIp, dpnId, result.getErrors());
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onRemoveFloatingIp(final BigInteger dpnId, String routerId, Uuid networkId, final String externalIp,
+ String internalIp, final long label) {
+ final String vpnName = NatUtil.getAssociatedVPN(dataBroker, networkId, LOG);
+ if(vpnName == null) {
+ LOG.info("No VPN associated with ext nw {} to handle remove floating ip configuration {} in router {}",
+ networkId, externalIp, routerId);
+ return;
+ }
+ //Remove Prefix from BGP
+ String rd = NatUtil.getVpnRd(dataBroker, vpnName);
+ removePrefixFromBGP(rd, externalIp + "/32");
+
+ //Remove custom FIB routes
+ //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
+ RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp + "/32").setServiceId(label).build();
+ Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
+
+ ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future), new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
+
+ @Override
+ public ListenableFuture<RpcResult<Void>> apply(RpcResult<Void> result) throws Exception {
+ //Release label
+ if(result.isSuccessful()) {
+ removeTunnelTableEntry(dpnId, label);
+ removeLFibTableEntry(dpnId, label);
+ RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
+ Future<RpcResult<Void>> labelFuture = vpnService.removeVpnLabel(labelInput);
+ return JdkFutureAdapters.listenInPoolThread(labelFuture);
+ } else {
+ String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
+ LOG.error(errMsg);
+ return Futures.immediateFailedFuture(new RuntimeException(errMsg));
+ }
+ }
+ });
+
+ Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
+
+ @Override
+ public void onFailure(Throwable error) {
+ LOG.error("Error in removing the label or custom fib entries", error);
+ }
+
+ @Override
+ public void onSuccess(RpcResult<Void> result) {
+ if(result.isSuccessful()) {
+ LOG.debug("Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
+ } else {
+ LOG.error("Error in removing the label for prefix {} from VPN {}, {}", externalIp, vpnName, result.getErrors());
+ }
+ }
+ });
+ }
+
+ private void removePrefixFromBGP(String rd, String prefix) {
+ try {
+ bgpManager.deletePrefix(rd, prefix);
+ } catch(Exception e) {
+ LOG.error("Delete prefix failed", e);
+ }
+ }
+
+ void cleanupFibEntries(final BigInteger dpnId, final String vpnName, final String externalIp, final long label ) {
+ //Remove Prefix from BGP
+ String rd = NatUtil.getVpnRd(dataBroker, vpnName);
+ removePrefixFromBGP(rd, externalIp + "/32");
+
+ //Remove custom FIB routes
+
+ //Future<RpcResult<java.lang.Void>> removeFibEntry(RemoveFibEntryInput input);
+ RemoveFibEntryInput input = new RemoveFibEntryInputBuilder().setVpnName(vpnName).setSourceDpid(dpnId).setIpAddress(externalIp).setServiceId(label).build();
+ Future<RpcResult<Void>> future = fibService.removeFibEntry(input);
+
+ ListenableFuture<RpcResult<Void>> labelFuture = Futures.transform(JdkFutureAdapters.listenInPoolThread(future),
+ new AsyncFunction<RpcResult<Void>, RpcResult<Void>>() {
+
+ @Override
+ public ListenableFuture<RpcResult<Void>> apply(RpcResult<Void> result) throws Exception {
+ //Release label
+ if(result.isSuccessful()) {
+ removeTunnelTableEntry(dpnId, label);
+ removeLFibTableEntry(dpnId, label);
+ RemoveVpnLabelInput labelInput = new RemoveVpnLabelInputBuilder().setVpnName(vpnName).setIpPrefix(externalIp).build();
+ Future<RpcResult<Void>> labelFuture = vpnService.removeVpnLabel(labelInput);
+ return JdkFutureAdapters.listenInPoolThread(labelFuture);
+ } else {
+ String errMsg = String.format("RPC call to remove custom FIB entries on dpn %s for prefix %s Failed - %s", dpnId, externalIp, result.getErrors());
+ LOG.error(errMsg);
+ return Futures.immediateFailedFuture(new RuntimeException(errMsg));
+ }
+ }
+ });
+
+ Futures.addCallback(labelFuture, new FutureCallback<RpcResult<Void>>() {
+
+ @Override
+ public void onFailure(Throwable error) {
+ LOG.error("Error in removing the label or custom fib entries", error);
+ }
+
+ @Override
+ public void onSuccess(RpcResult<Void> result) {
+ if(result.isSuccessful()) {
+ LOG.debug("Successfully removed the label for the prefix {} from VPN {}", externalIp, vpnName);
+ } else {
+ LOG.error("Error in removing the label for prefix {} from VPN {}, {}", externalIp, vpnName, result.getErrors());
+ }
+ }
+ });
+ }
+
+ private String getFlowRef(BigInteger dpnId, short tableId, long id, String ipAddress) {
+ return new StringBuilder(64).append(FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
+ .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
+ .append(id).append(NwConstants.FLOWID_SEPARATOR).append(ipAddress).toString();
+ }
+
+ private void removeTunnelTableEntry(BigInteger dpnId, long serviceId) {
+ LOG.info("remove terminatingServiceActions called with DpnId = {} and label = {}", dpnId , serviceId);
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+ // Matching metadata
+ mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
+ Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
+ getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""),
+ 5, String.format("%s:%d","TST Flow Entry ",serviceId), 0, 0,
+ COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)), mkMatches, null);
+ mdsalManager.removeFlow(dpnId, flowEntity);
+ LOG.debug("Terminating service Entry for dpID {} : label : {} removed successfully {}",dpnId, serviceId);
+ }
+
+ private void makeTunnelTableEntry(BigInteger dpnId, long serviceId, List<Instruction> customInstructions) {
+ List<MatchInfo> mkMatches = new ArrayList<MatchInfo>();
+
+ LOG.info("create terminatingServiceAction on DpnId = {} and serviceId = {} and actions = {}", dpnId , serviceId);
+
+ mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] {BigInteger.valueOf(serviceId)}));
+
+ Flow terminatingServiceTableFlowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
+ getFlowRef(dpnId, NwConstants.INTERNAL_TUNNEL_TABLE, serviceId, ""), 5, String.format("%s:%d","TST Flow Entry ",serviceId),
+ 0, 0, COOKIE_TUNNEL.add(BigInteger.valueOf(serviceId)),mkMatches, customInstructions);
+
+ mdsalManager.installFlow(dpnId, terminatingServiceTableFlowEntity);
+ }
+
+ private void makeLFibTableEntry(BigInteger dpId, long serviceId, long tableId) {
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x8847L }));
+ matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
+
+ List<Instruction> instructions = new ArrayList<Instruction>();
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+ actionsInfos.add(new ActionInfo(ActionType.pop_mpls, new String[]{}));
+ Instruction writeInstruction = new InstructionInfo(InstructionType.apply_actions, actionsInfos).buildInstruction(0);
+ instructions.add(writeInstruction);
+ instructions.add(new InstructionInfo(InstructionType.goto_table, new long[]{tableId}).buildInstruction(1));
+
+ // Install the flow entry in L3_LFIB_TABLE
+ String flowRef = getFlowRef(dpId, NwConstants.L3_LFIB_TABLE, serviceId, "");
+
+ Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
+ 10, flowRef, 0, 0,
+ COOKIE_VM_LFIB_TABLE, matches, instructions);
+
+ mdsalManager.installFlow(dpId, flowEntity);
+
+ LOG.debug("LFIB Entry for dpID {} : label : {} modified successfully {}",dpId, serviceId );
+ }
+
+ private void removeLFibTableEntry(BigInteger dpnId, long serviceId) {
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x8847L }));
+ matches.add(new MatchInfo(MatchFieldType.mpls_label, new String[]{Long.toString(serviceId)}));
+
+ String flowRef = getFlowRef(dpnId, NwConstants.L3_LFIB_TABLE, serviceId, "");
+
+ LOG.debug("removing LFib entry with flow ref {}", flowRef);
+
+ Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_LFIB_TABLE, flowRef,
+ 10, flowRef, 0, 0,
+ COOKIE_VM_LFIB_TABLE, matches, null);
+
+ mdsalManager.removeFlow(dpnId, flowEntity);
+
+ LOG.debug("LFIB Entry for dpID : {} label : {} removed successfully {}",dpnId, serviceId);
+ }
+
+}
+
--- /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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.natservice.impl.rev160111;
+
+import org.opendaylight.vpnservice.natservice.internal.NatServiceProvider;
+
+public class NATServiceModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.natservice.impl.rev160111.AbstractNATServiceModule {
+ public NATServiceModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public NATServiceModule(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.natservice.impl.rev160111.NATServiceModule 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() {
+ NatServiceProvider provider = new NatServiceProvider(getRpcRegistryDependency());
+ provider.setNotificationService(getNotificationServiceDependency());
+ provider.setMdsalManager(getMdsalutilDependency());
+ provider.setBgpManager(getBgpmanagerDependency());
+ getBrokerDependency().registerProvider(provider);
+ return provider;
+ }
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: natmanager-impl yang module local name: natservice-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Wed Jan 20 15:47:25 IST 2016
+*
+* 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.natservice.impl.rev160111;
+public class NATServiceModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.natservice.impl.rev160111.AbstractNATServiceModuleFactory {
+
+}
--- /dev/null
+module natservice-impl {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:natservice:impl";
+ prefix "natservice-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 odl-mdsalutil { prefix odl-mdsal; revision-date 2015-04-10;}
+ import bgpmanager-api { prefix bgpmgr-api; revision-date 2015-04-20;}
+
+ description
+ "Service definition for NAT Service module";
+
+ revision "2016-01-11" {
+ description
+ "Initial revision";
+ }
+
+ identity natservice-impl {
+ base config:module-type;
+ config:java-name-prefix NATService;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case natservice-impl {
+ when "/config:modules/config:module/config:type = 'natservice-impl'";
+ container broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-broker-osgi-registry;
+ }
+ }
+ }
+ container rpc-registry {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-rpc-registry;
+ }
+ }
+ }
+ container bgpmanager {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity bgpmgr-api:bgpmanager-api;
+ }
+ }
+ }
+ container notification-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding-impl:binding-new-notification-service;
+ }
+ }
+ }
+ container mdsalutil {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity odl-mdsal:odl-mdsalutil;
+ }
+ }
+ }
+ }
+ }
+}
\ 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.natservice.internal.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.mock;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+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.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.ActionType;
+import org.opendaylight.vpnservice.mdsalutil.BucketInfo;
+import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
+import org.opendaylight.vpnservice.mdsalutil.GroupEntity;
+import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
+import org.opendaylight.vpnservice.mdsalutil.InstructionType;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.vpnservice.natservice.internal.ExternalNetworksChangeListener;
+import org.opendaylight.vpnservice.natservice.internal.NatUtil;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(MDSALUtil.class)
+public class ExternalNetworksChangeListenerTest {
+
+ @Mock DataBroker dataBroker;
+ @Mock ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
+ @Mock IMdsalApiManager mdsalManager;
+ @Mock FlowEntity flowMock;
+ @Mock GroupEntity groupMock;
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.networks.Networks> id = null;
+ org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.external.networks.Networks networks = null;
+ private ExternalNetworksChangeListener extNetworks;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(dataBroker.registerDataChangeListener(
+ any(LogicalDatastoreType.class),
+ any(InstanceIdentifier.class),
+ any(DataChangeListener.class),
+ any(DataChangeScope.class)))
+ .thenReturn(dataChangeListenerRegistration);
+ extNetworks = new ExternalNetworksChangeListener(dataBroker);
+
+ PowerMockito.mockStatic(MDSALUtil.class);
+ }
+
+
+ @Test
+ public void testSnatFlowEntity() {
+ FlowEntity flowMock = mock(FlowEntity.class);
+ final short SNAT_TABLE = 40;
+ final int DEFAULT_SNAT_FLOW_PRIORITY = 0;
+ final String FLOWID_SEPARATOR = ".";
+ String SNAT_FLOWID_PREFIX = "SNAT.";
+
+
+ BigInteger dpnId = new BigInteger("100");
+ String routerName = new String("200");
+ long routerId = 200;
+ long groupId = 300;
+ List<BucketInfo> bucketInfo = new ArrayList<BucketInfo>();
+ List<ActionInfo> listActionInfoPrimary = new ArrayList<ActionInfo>();
+ listActionInfoPrimary.add(new ActionInfo(ActionType.output,
+ new String[] {"3"}));
+ BucketInfo bucketPrimary = new BucketInfo(listActionInfoPrimary);
+ List<ActionInfo> listActionInfoSecondary = new ArrayList<ActionInfo>();
+ listActionInfoSecondary.add(new ActionInfo(ActionType.output,
+ new String[] {"4"}));
+ BucketInfo bucketSecondary = new BucketInfo(listActionInfoPrimary);
+ bucketInfo.add(0, bucketPrimary);
+ bucketInfo.add(1, bucketSecondary);
+
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ matches.add(new MatchInfo(MatchFieldType.eth_type,
+ new long[] { 0x0800L }));
+
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+ actionsInfos.add(new ActionInfo(ActionType.group, new String[] {String.valueOf(groupId)}));
+ instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos));
+
+
+ String flowRef = new StringBuffer().append(SNAT_FLOWID_PREFIX).append(dpnId).append(FLOWID_SEPARATOR).
+ append(SNAT_TABLE).append(FLOWID_SEPARATOR).append(routerId).toString();
+
+ BigInteger cookieSnat = NatUtil.getCookieSnatFlow(routerId);
+ try {
+ PowerMockito.when(MDSALUtil.class, "buildFlowEntity", dpnId, SNAT_TABLE, flowRef,
+ DEFAULT_SNAT_FLOW_PRIORITY, flowRef, 0, 0,
+ cookieSnat, matches, instructions ).thenReturn(flowMock);
+ } catch (Exception e) {
+ // Test failed anyways
+ assertEquals("true", "false");
+ }
+ /* TODO : Fix this to mock it properly when it reads DS
+ extNetworks.buildSnatFlowEntity(dpnId, routerName, groupId);
+ PowerMockito.verifyStatic(); */
+
+ }
+
+}
--- /dev/null
+package org.opendaylight.vpnservice.natservice.internal.test;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Matchers;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.OngoingStubbing;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.eq;
+
+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.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.natservice.internal.IPAddress;
+import org.opendaylight.vpnservice.natservice.internal.NaptManager;
+import org.opendaylight.vpnservice.natservice.internal.SessionAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.IntextIpMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.IntextIpPortMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMappingKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.IpPortMapping;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.port.map.IpPortMappingKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+import com.google.common.util.concurrent.Futures;
+
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(MDSALUtil.class)
+public class NaptManagerTest {
+
+ @Mock IdManagerService idMgr;
+ @Mock DataBroker dataBroker;
+ @Mock ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMap> ipmapId = null;
+ org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMap ipmap = null;
+
+ private NaptManager naptManager;
+
+ @Before
+ public void init() {
+ MockitoAnnotations.initMocks(this);
+ when(dataBroker.registerDataChangeListener(
+ any(LogicalDatastoreType.class),
+ any(InstanceIdentifier.class),
+ any(DataChangeListener.class),
+ any(DataChangeScope.class)))
+ .thenReturn(dataChangeListenerRegistration);
+ naptManager = new NaptManager(dataBroker);
+ when(idMgr.createIdPool(any(CreateIdPoolInput.class)))
+ .thenReturn(Futures.immediateFuture(RpcResultBuilder.<Void>success().build()));
+ naptManager.setIdManager(idMgr);
+
+ PowerMockito.mockStatic(MDSALUtil.class);
+
+ }
+
+
+ @Ignore @Test
+ public void testRegisterMappingIpIP() {
+ // TODO : This needs to be modified to make it work
+ // TODO : Issue with Mockito.any() usage, so for now run registerMapping testcases as seperate Tests. This needs to be fixed properly.
+ ipmapId = InstanceIdentifier.builder(
+ IntextIpMap.class).child(IpMapping.class, new IpMappingKey(5L)).child(IpMap.class, new IpMapKey("10.0.0.1")).build();
+ ipmap = new IpMapBuilder().setKey(new IpMapKey("10.0.0.1")).setInternalIp("10.0.0.1").setExternalIp("192.17.13.1").build();
+ try {
+ PowerMockito.doNothing().when(MDSALUtil.class, "syncWrite", dataBroker, LogicalDatastoreType.OPERATIONAL, ipmapId, ipmap);
+ } catch (Exception e) {
+ // Test failed anyways
+ assertEquals("true", "false");
+ }
+ IPAddress internal = new IPAddress("10.0.0.1",0);
+ IPAddress external = new IPAddress("192.17.13.1", 0);
+ naptManager.registerMapping(5, internal, external);
+ PowerMockito.verifyStatic();
+
+ }
+
+ @Ignore @Test
+ public void testRegisterMappingIpSubnet() {
+ // TODO : This needs to be modified to make it work
+ ipmapId = InstanceIdentifier.builder(
+ IntextIpMap.class).child(IpMapping.class, new IpMappingKey(5L)).child(IpMap.class, new IpMapKey("10.0.0.1")).build();
+ ipmap = new IpMapBuilder().setKey(new IpMapKey("10.0.0.1")).setInternalIp("10.0.0.1").setExternalIp("192.17.13.1/24").build();
+ try {
+ PowerMockito.doNothing().when(MDSALUtil.class, "syncWrite", dataBroker, LogicalDatastoreType.OPERATIONAL, ipmapId, ipmap);
+ } catch (Exception e) {
+ // Test failed anyways
+ assertEquals("true", "false");
+ }
+ IPAddress internal = new IPAddress("10.0.0.1",0);
+ IPAddress external = new IPAddress("192.17.13.1", 24);
+ naptManager.registerMapping(5, internal, external);
+ PowerMockito.verifyStatic();
+ }
+
+ @Ignore @Test
+ public void testRegisterMappingSubnetIp() {
+ // TODO : This needs to be modified to make it work
+ ipmapId = InstanceIdentifier.builder(
+ IntextIpMap.class).child(IpMapping.class, new IpMappingKey(6L)).child(IpMap.class, new IpMapKey("10.0.2.1/16")).build();
+ ipmap = new IpMapBuilder().setKey(new IpMapKey("10.0.0.1")).setInternalIp("10.0.0.1").setExternalIp("192.19.15.3").build();
+ try {
+ PowerMockito.doNothing().when(MDSALUtil.class, "syncWrite", dataBroker, LogicalDatastoreType.OPERATIONAL, ipmapId, ipmap);
+ } catch (Exception e) {
+ // Test failed anyways
+ assertEquals("true", "false");
+ }
+ IPAddress internal = new IPAddress("10.0.2.1",16);
+ IPAddress external = new IPAddress("192.19.15.3", 0);
+ naptManager.registerMapping(6, internal, external);
+ PowerMockito.verifyStatic();
+ }
+
+ @Ignore @Test
+ public void testRegisterMappingSubnetSubnet() {
+ // TODO : This needs to be modified to make it work
+ ipmapId = InstanceIdentifier.builder(
+ IntextIpMap.class).child(IpMapping.class, new IpMappingKey(6L)).child(IpMap.class, new IpMapKey("10.2.0.1/24")).build();
+ ipmap = new IpMapBuilder().setKey(new IpMapKey("10.2.0.1/24")).setInternalIp("10.2.0.1/24").setExternalIp("192.21.16.1/16").build();
+ try {
+ PowerMockito.doNothing().when(MDSALUtil.class, "syncWrite", dataBroker, LogicalDatastoreType.OPERATIONAL, ipmapId, ipmap);
+ } catch (Exception e) {
+ // Test failed anyways
+ assertEquals("true", "false");
+ }
+ IPAddress internal = new IPAddress("10.2.0.1",24);
+ IPAddress external = new IPAddress("192.21.16.1", 16);
+ naptManager.registerMapping(6, internal, external);
+ PowerMockito.verifyStatic();
+ }
+
+
+ @Test
+ public void testgetExternalAddressMapping() {
+ // TODO : This needs to be modified to make it work
+ // Testcase to test when no entry exists in ip-pot-map
+ /*SessionAddress internalIpPort = new SessionAddress("10.0.0.1", 2);
+ InstanceIdentifierBuilder<IpPortMapping> idBuilder =
+ InstanceIdentifier.builder(IntextIpPortMap.class).child(IpPortMapping.class, new IpPortMappingKey(5L));
+ InstanceIdentifier<IpPortMapping> id = idBuilder.build();
+ try {
+ PowerMockito.when(MDSALUtil.class, "read", dataBroker, LogicalDatastoreType.CONFIGURATION, id).thenReturn(null);
+ } catch (Exception e) {
+ // Test failed anyways
+ assertEquals("true", "false");
+ }
+ naptManager.getExternalAddressMapping(5, internalIpPort);
+ PowerMockito.verifyStatic(); */
+ }
+
+ @Test
+ public void testReleaseAddressMapping() {
+ // TODO : Below needs to be modified to make it work
+ /* InstanceIdentifierBuilder<IpMapping> idBuilder =
+ InstanceIdentifier.builder(IntextIpMap.class).child(IpMapping.class, new IpMappingKey(5L));
+ InstanceIdentifier<IpMapping> id = idBuilder.build();
+ try {
+ PowerMockito.doNothing().when(MDSALUtil.class, "read", dataBroker, LogicalDatastoreType.OPERATIONAL, id);
+ } catch (Exception e) {
+ // Test failed anyways
+ assertEquals("true", "false");
+ }
+ IPAddress internal = new IPAddress("10.0.0.1",0);
+ IPAddress external = new IPAddress("192.17.13.1", 0);
+ naptManager.registerMapping(5, internal, external);
+ SessionAddress internalSession = new SessionAddress("10.0.0.1", 0);
+ naptManager.releaseAddressMapping(5L, internalSession);*/
+ }
+
+
+}
--- /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.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>natservice-aggregator</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <name>natservice</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>natservice-api</module>
+ <module>natservice-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>
--- /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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>neutronvpn-api</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>yang-binding</artifactId>
+ <version>${mdsal.model.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ <version>${yangtools.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.neutron</groupId>
+ <artifactId>model</artifactId>
+ <version>${neutron.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-yang-types</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>mdsalutil-api</artifactId>
+ <version>${vpns.mdsalutil.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.vpnservice.neutronvpn.api.l2gw;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+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.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LocalUcastMacs;
+
+/**
+ * The Class L2GatewayDevice.
+ */
+public class L2GatewayDevice {
+
+ /** The device name. */
+ String deviceName;
+
+ /** The hwvtep node id. */
+ String hwvtepNodeId;
+
+ /** The tunnel ips. */
+ List<IpAddress> tunnelIps = new ArrayList<IpAddress>();
+
+ /** The l2 gateway ids. */
+ List<Uuid> l2GatewayIds = new ArrayList<Uuid>();
+
+ /** The ucast local macs. */
+ List<LocalUcastMacs> ucastLocalMacs = Collections.synchronizedList(new ArrayList<LocalUcastMacs>());
+
+ /** the status of this device connectin */
+ AtomicBoolean connected = new AtomicBoolean(true);
+
+ /**
+ * VTEP device name mentioned with L2 Gateway.
+ *
+ * @return the device name
+ */
+ public String getDeviceName() {
+ return deviceName;
+ }
+
+ /**
+ * Sets the device name.
+ *
+ * @param deviceName
+ * the new device name
+ */
+ public void setDeviceName(String deviceName) {
+ this.deviceName = deviceName;
+ }
+
+ /**
+ * VTEP Node id for the device mentioned with L2 Gateway.
+ *
+ * @return the hwvtep node id
+ */
+ public String getHwvtepNodeId() {
+ return hwvtepNodeId;
+ }
+
+ /**
+ * Sets the hwvtep node id.
+ *
+ * @param nodeId
+ * the new hwvtep node id
+ */
+ public void setHwvtepNodeId(String nodeId) {
+ this.hwvtepNodeId = nodeId;
+ }
+
+ /**
+ * Tunnel IP created with in the device mentioned with L2 Gateway.
+ *
+ * @return the tunnel ips
+ */
+ public List<IpAddress> getTunnelIps() {
+ return tunnelIps;
+ }
+
+ /**
+ * Gets the tunnel ip.
+ *
+ * @return the tunnel ip
+ */
+ public IpAddress getTunnelIp() {
+ if (tunnelIps.size() > 0) {
+ return tunnelIps.get(0);
+ }
+ return null;
+ }
+
+ /**
+ * Adds the tunnel ip.
+ *
+ * @param tunnelIp
+ * the tunnel ip
+ */
+ public void addTunnelIp(IpAddress tunnelIp) {
+ tunnelIps.add(tunnelIp);
+ }
+
+ /**
+ * UUID representing L2Gateway.
+ *
+ * @return the l2 gateway ids
+ */
+ public List<Uuid> getL2GatewayIds() {
+ return l2GatewayIds;
+ }
+
+ /**
+ * Adds the l2 gateway id.
+ *
+ * @param l2GatewayId
+ * the l2 gateway id
+ */
+ public void addL2GatewayId(Uuid l2GatewayId) {
+ l2GatewayIds.add(l2GatewayId);
+ }
+
+ /**
+ * Removes the l2 gateway id.
+ *
+ * @param l2GatewayId
+ * the l2 gateway id
+ */
+ public void removeL2GatewayId(Uuid l2GatewayId) {
+ l2GatewayIds.remove(l2GatewayId);
+ }
+
+ /**
+ * Clear hwvtep node data.
+ */
+ public void clearHwvtepNodeData() {
+ tunnelIps.clear();
+ hwvtepNodeId = null;
+ }
+
+ /**
+ * Sets the tunnel ips.
+ *
+ * @param tunnelIps
+ * the new tunnel ips
+ */
+ public void setTunnelIps(List<IpAddress> tunnelIps) {
+ this.tunnelIps = tunnelIps;
+ }
+
+ /**
+ * Gets the ucast local macs.
+ *
+ * @return the ucast local macs
+ */
+ public List<LocalUcastMacs> getUcastLocalMacs() {
+ return new ArrayList<>(ucastLocalMacs);
+ }
+
+ /**
+ * Adds the ucast local mac.
+ *
+ * @param localUcastMacs
+ * the local ucast macs
+ */
+ public void addUcastLocalMac(LocalUcastMacs localUcastMacs) {
+ ucastLocalMacs.add(localUcastMacs);
+ }
+
+ /**
+ * Removes the ucast local mac.
+ *
+ * @param localUcastMacs
+ * the local ucast macs
+ */
+ public void removeUcastLocalMac(LocalUcastMacs localUcastMacs) {
+ ucastLocalMacs.remove(localUcastMacs);
+ }
+
+ public boolean isConnected() {
+ return connected.get();
+ }
+
+ public void setConnected(boolean connected) {
+ this.connected.set(connected);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((deviceName == null) ? 0 : deviceName.hashCode());
+ result = prime * result + ((hwvtepNodeId == null) ? 0 : hwvtepNodeId.hashCode());
+ result = prime * result + ((l2GatewayIds == null) ? 0 : l2GatewayIds.hashCode());
+ result = prime * result + ((tunnelIps == null) ? 0 : tunnelIps.hashCode());
+ result = prime * result + ((ucastLocalMacs == null) ? 0 : ucastLocalMacs.hashCode());
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ L2GatewayDevice other = (L2GatewayDevice) obj;
+ if (deviceName == null) {
+ if (other.deviceName != null) {
+ return false;
+ }
+ } else if (!deviceName.equals(other.deviceName)) {
+ return false;
+ }
+ if (hwvtepNodeId == null) {
+ if (other.hwvtepNodeId != null) {
+ return false;
+ }
+ } else if (!hwvtepNodeId.equals(other.hwvtepNodeId)) {
+ return false;
+ }
+ if (l2GatewayIds == null) {
+ if (other.l2GatewayIds != null) {
+ return false;
+ }
+ } else if (!l2GatewayIds.equals(other.l2GatewayIds)) {
+ return false;
+ }
+ if (tunnelIps == null) {
+ if (other.tunnelIps != null) {
+ return false;
+ }
+ } else if (!tunnelIps.equals(other.tunnelIps)) {
+ return false;
+ }
+ if (ucastLocalMacs == null) {
+ if (other.ucastLocalMacs != null) {
+ return false;
+ }
+ } else if (!ucastLocalMacs.equals(other.ucastLocalMacs)) {
+ return false;
+ }
+ return true;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("L2GatewayDevice [deviceName=").append(deviceName).append(", hwvtepNodeId=").append(hwvtepNodeId)
+ .append(", tunnelIps=").append(tunnelIps).append(", l2GatewayIds=").append(l2GatewayIds)
+ .append(", ucastLocalMacs=").append(ucastLocalMacs).append("]");
+ return builder.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.neutronvpn.api.l2gw.utils;
+
+import java.util.concurrent.ConcurrentMap;
+
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.vpnservice.utils.cache.CacheUtil;
+
+public class L2GatewayCacheUtils {
+ public static final String L2GATEWAY_CACHE_NAME = "L2GW";
+
+ public static void createL2DeviceCache() {
+ if (CacheUtil.getCache(L2GatewayCacheUtils.L2GATEWAY_CACHE_NAME) == null) {
+ CacheUtil.createCache(L2GatewayCacheUtils.L2GATEWAY_CACHE_NAME);
+ }
+ }
+
+ public static void addL2DeviceToCache(String devicename, L2GatewayDevice l2GwDevice) {
+ ConcurrentMap<String, L2GatewayDevice> cachedMap = (ConcurrentMap<String, L2GatewayDevice>) CacheUtil
+ .getCache(L2GatewayCacheUtils.L2GATEWAY_CACHE_NAME);
+ cachedMap.put(devicename, l2GwDevice);
+ }
+
+ public static L2GatewayDevice removeL2DeviceFromCache(String devicename) {
+ ConcurrentMap<String, L2GatewayDevice> cachedMap = (ConcurrentMap<String, L2GatewayDevice>) CacheUtil
+ .getCache(L2GatewayCacheUtils.L2GATEWAY_CACHE_NAME);
+ return cachedMap.remove(devicename);
+ }
+
+ public static L2GatewayDevice getL2DeviceFromCache(String devicename) {
+ ConcurrentMap<String, L2GatewayDevice> cachedMap = (ConcurrentMap<String, L2GatewayDevice>) CacheUtil
+ .getCache(L2GatewayCacheUtils.L2GATEWAY_CACHE_NAME);
+ return cachedMap.get(devicename);
+ }
+
+ public static ConcurrentMap<String, L2GatewayDevice> getCache() {
+ return (ConcurrentMap<String, L2GatewayDevice>) CacheUtil
+ .getCache(L2GatewayCacheUtils.L2GATEWAY_CACHE_NAME);
+ }
+}
--- /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.neutronvpn.api.utils;
+
+import java.util.List;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.neutron.networks.network.Segments;
+
+public class NeutronUtils {
+ public static final String VNIC_TYPE_NORMAL = "normal";
+
+ public static boolean isPortVnicTypeNormal(Port port) {
+ PortBindingExtension portBinding = port.getAugmentation(PortBindingExtension.class);
+ if(portBinding == null || portBinding.getVnicType() == null) {
+ // By default, VNIC_TYPE is NORMAL
+ return true;
+ }
+ String vnicType = portBinding.getVnicType().trim().toLowerCase();
+ return vnicType.equals(VNIC_TYPE_NORMAL);
+ }
+
+ public static String getSegmentationIdFromNeutronNetwork(Network network) {
+ String segmentationId = null;
+ NetworkProviderExtension providerExtension = network.getAugmentation(NetworkProviderExtension.class);
+ if (providerExtension != null) {
+ segmentationId = providerExtension.getSegmentationId();
+ if (segmentationId == null) {
+ List<Segments> providerSegments = providerExtension.getSegments();
+ if (providerSegments != null && providerSegments.size() > 0) {
+ for (Segments providerSegment: providerSegments) {
+ if (isNetworkSegmentTypeVxlan(providerSegment)) {
+ segmentationId = providerSegment.getSegmentationId();
+ break;
+ }
+ }
+ }
+ }
+ }
+ return segmentationId;
+ }
+
+ static boolean isNetworkSegmentTypeVxlan(Segments providerSegment) {
+ Class<? extends NetworkTypeBase> networkType = providerSegment.getNetworkType();
+ return (networkType != null && networkType.isAssignableFrom(NetworkTypeVxlan.class));
+ }
+}
--- /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.neutronvpn.interfaces;
+
+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.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+
+import java.util.List;
+
+public interface INeutronVpnManager {
+
+ public void addSubnetToVpn(Uuid vpnId, Uuid subnet);
+
+ public void removeSubnetFromVpn(Uuid vpnId, Uuid subnet);
+
+ public List<Uuid> getSubnetsforVpn(Uuid vpnid);
+
+ List<String> showVpnConfigCLI(Uuid vuuid);
+
+ List<String> showNeutronPortsCLI();
+
+ public Port getNeutronPort(String name);
+
+ public Subnet getNeutronSubnet(Uuid subnetId);
+
+ public String uuidToTapPortName(Uuid id);
+
+ public Port getNeutronPort(Uuid portId);
+
+ public IpAddress getNeutronSubnetGateway(Uuid subnetId);
+
+}
--- /dev/null
+module neutronvpn-api {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:neutronvpn:api";
+ prefix "neutronvpn-api";
+
+ import config { prefix config; revision-date 2013-04-05; }
+
+ description
+ "Service definition for neutronvpn project";
+
+ revision "2015-08-12" {
+ description
+ "Initial revision";
+ }
+
+ identity neutronvpn-api {
+ base "config:service-type";
+ config:java-class "org.opendaylight.vpnservice.neutronvpn.interfaces.INeutronVpnManager";
+ }
+}
--- /dev/null
+
+module neutronvpn {
+
+ namespace "urn:opendaylight:vpnservice:neutronvpn";
+ prefix neutronvpn;
+
+ import ietf-yang-types { prefix "yang"; }
+
+ revision "2015-06-02" {
+ description "Neutron based L3Service Module, provides integration of ODL VPN service with Neutron NSF";
+ }
+
+ container subnetmaps{
+ list subnetmap {
+ key id;
+ leaf id {
+ type yang:uuid;
+ description "UUID representing the subnet ";
+ }
+
+ leaf subnet-ip {
+ type string;
+ description "Specifies the subnet IP in CIDR format";
+ }
+
+ leaf tenant-id {
+ type yang:uuid;
+ description "The UUID of the tenant that will own the subnet.";
+ }
+
+ leaf network-id {
+ type yang:uuid;
+ description "UUID representing the network ";
+ }
+
+ leaf router-id {
+ type yang:uuid;
+ description "router to which this subnet belongs";
+ }
+
+ leaf vpn-id {
+ type yang:uuid;
+ description "VPN to which this subnet belongs";
+ }
+
+ leaf-list port-list {
+ type yang:uuid;
+ }
+ }
+ }
+
+ container networkMaps{
+ list networkMap {
+ key network-id;
+
+ leaf network-id {
+ type yang:uuid;
+ description "UUID representing the network";
+ }
+
+ leaf-list subnet-id-list {
+ type yang:uuid;
+ description "List of UUIDs representing the subnets associated to the network";
+ }
+ }
+ }
+
+ grouping l3vpn-instance{
+
+ leaf id {
+ mandatory "true";
+ type yang:uuid;
+ description "vpn-id";
+ }
+
+ leaf name {
+ type string;
+ description "VPN name";
+ }
+
+ leaf tenant-id {
+ type yang:uuid;
+ description "The UUID of the tenant that will own the subnet.";
+ }
+
+ leaf-list route-distinguisher {
+ type string;
+ description
+ "configures a route distinguisher (RD) for the VPN instance.
+ Format is ASN:nn or IP-address:nn.";
+ }
+
+ leaf-list import-RT {
+ type string;
+ description
+ "configures a list of import route target.
+ Format is ASN:nn or IP-address:nn.";
+ }
+
+ leaf-list export-RT{
+ type string;
+ description
+ "configures a list of export route targets.
+ Format is ASN:nn or IP-address:nn.";
+ }
+
+ leaf router-id {
+ type yang:uuid;
+ description "UUID of router ";
+ }
+
+ leaf-list network-ids {
+ type yang:uuid;
+ description "UUID representing the network ";
+ }
+ }
+
+ container vpnMaps {
+ list vpnMap {
+ key vpn-id;
+ leaf vpn-id {
+ type yang:uuid;
+ description "vpn-id";
+ }
+ leaf name {
+ type string;
+ description "vpn name";
+ }
+ leaf tenant-id {
+ type yang:uuid;
+ description "The UUID of the tenant that will own the subnet.";
+ }
+
+ leaf router-id {
+ type yang:uuid;
+ description "UUID of router ";
+ }
+ leaf-list network_ids {
+ type yang:uuid;
+ description "UUID representing the network ";
+ }
+ }
+ }
+
+ /* Data models to adhere to restart requirements */
+ container neutron-port-data {
+ list port-fixedip-to-port-name {
+ key port-fixedip;
+ leaf port-name { type string;}
+ leaf port-fixedip { type string;}
+ }
+ }
+
+
+ container router-interfaces-map {
+ list router-interfaces {
+ key router-id;
+ leaf router-id { type yang:uuid; }
+ list interfaces {
+ key interface-id;
+ leaf interface-id { type string; }
+ }
+ }
+ }
+
+
+ /* container for DHCP Configuration */
+ container dhcp-config {
+ list configs {
+ leaf lease-duration {
+ type int32;
+ description "default lease duration for dhcp lease.
+ -1 means infinite";
+ }
+ leaf default-domain {
+ type string;
+ description "default domain-name. used in dhcp reply";
+ }
+ }
+ }
+
+ rpc createL3VPN{
+ description "Create one or more L3 VPN";
+ input {
+ list l3vpn {
+ uses l3vpn-instance;
+ }
+ }
+ output {
+ leaf-list response {
+ type string;
+ description "Status response for createVPN RPC";
+ }
+ }
+ }
+
+ rpc associateRouter {
+ description "associates a router with L3VPN";
+ input {
+ leaf vpn-id {
+ type yang:uuid;
+ mandatory "true";
+ description "vpn-id";
+ }
+ leaf router-id {
+ type yang:uuid;
+ mandatory "true";
+ description "vpn-id";
+ }
+ }
+ }
+
+ rpc dissociateRouter {
+ description "dissociates a router with L3VPN";
+ input {
+ leaf vpn-id {
+ type yang:uuid;
+ mandatory "true";
+ description "vpn-id";
+ }
+ leaf router-id {
+ type yang:uuid;
+ mandatory "true";
+ description "router-id";
+ }
+ }
+ }
+
+ rpc associateNetworks {
+ description "associates a list of networks with L3VPN";
+ input {
+ leaf vpn-id {
+ type yang:uuid;
+ mandatory "true";
+ description "vpn-id";
+ }
+ leaf-list network-id {
+ type yang:uuid;
+ description "network-id";
+ }
+ }
+ output {
+ leaf response {
+ type string;
+ description "Status response for associateNetworks RPC";
+ }
+ }
+ }
+
+ rpc dissociateNetworks{
+ description "dissociates a list of networks with L3VPN";
+ input {
+ leaf vpn-id {
+ type yang:uuid;
+ mandatory "true";
+ description "vpn-id";
+ }
+ leaf-list network-id {
+ type yang:uuid;
+ description "network-id";
+ }
+ }
+ output {
+ leaf response {
+ type string;
+ description "Status response for dissociateNetworks RPC";
+ }
+ }
+ }
+
+ rpc deleteL3VPN{
+ description "delete VPNs for specified Id list";
+ input {
+ leaf-list id {
+ type yang:uuid;
+ description "vpn-id";
+ }
+ }
+ output {
+ leaf-list response {
+ type string;
+ description "Status response for deleteL3VPN RPC";
+ }
+ }
+ }
+
+ rpc getL3VPN{
+ description "returns VPN configuration";
+ input {
+ leaf id {
+ type yang:uuid;
+ description "vpn-id";
+ }
+ }
+ output {
+ list l3vpn-instances {
+ uses l3vpn-instance;
+ }
+ }
+ }
+
+ rpc get-fixedIPs-for-neutron-port {
+ description "returns neutron port fixed IPs";
+ input {
+ leaf port-id {
+ type yang:uuid;
+ }
+ }
+ output {
+ leaf-list fixedIPs {
+ type string;
+ description "The neutron port fixedIPs list corresponding to the port uuid";
+ }
+ }
+ }
+
+ notification subnet-added-to-vpn{
+ description "new subnet added to vpn";
+ leaf subnet-id {
+ type yang:uuid;
+ }
+ leaf subnet-ip {
+ type string;
+ }
+ leaf vpn-name {
+ type string;
+ }
+ leaf external-vpn {
+ type boolean;
+ }
+ leaf elan-tag {
+ type uint32;
+ }
+ }
+
+ notification subnet-deleted-from-vpn{
+ description "subnet deleted from vpn";
+ leaf subnet-id {
+ type yang:uuid;
+ }
+ leaf subnet-ip {
+ type string;
+ }
+ leaf vpn-name {
+ type string;
+ }
+ leaf external-vpn {
+ type boolean;
+ }
+ leaf elan-tag {
+ type uint32;
+ }
+ }
+
+ notification subnet-updated-in-vpn{
+ description "subnet updated in vpn";
+ leaf subnet-id {
+ type yang:uuid;
+ }
+ leaf subnet-ip {
+ type string;
+ }
+ leaf vpn-name {
+ type string;
+ }
+ leaf external-vpn {
+ type boolean;
+ }
+ leaf elan-tag {
+ type uint32;
+ }
+ }
+
+ notification port-added-to-subnet{
+ description "new port added to subnet";
+ leaf subnet-id{
+ type yang:uuid;
+ }
+ leaf subnet-ip{
+ type string;
+ }
+ leaf port-id{
+ type yang:uuid;
+ }
+ leaf elan-tag {
+ type uint32;
+ }
+ }
+
+ notification port-removed-from-subnet{
+ description "port removed from subnet";
+ leaf subnet-id{
+ type yang:uuid;
+ }
+ leaf subnet-ip{
+ type string;
+ }
+ leaf port-id{
+ type yang:uuid;
+ }
+ leaf elan-tag {
+ type uint32;
+ }
+ }
+
+ notification router-associated-to-vpn {
+ description "router association to vpn";
+ leaf router-id{
+ type yang:uuid;
+ }
+ leaf vpn-id{
+ type yang:uuid;
+ }
+ }
+
+ notification router-disassociated-from-vpn {
+ description "router disassociation from vpn";
+ leaf router-id{
+ type yang:uuid;
+ }
+ leaf vpn-id{
+ type yang:uuid;
+ }
+ }
+
+}
--- /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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>neutronvpn-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.neutron</groupId>
+ <artifactId>model</artifactId>
+ <version>${neutron.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>neutronvpn-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>vpnmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>elanmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>mdsalutil-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>lockmanager-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.ovsdb</groupId>
+ <artifactId>hwvtepsouthbound-api</artifactId>
+ <version>${vpns.ovsdb.version}</version>
+ </dependency>
+ </dependencies>
+
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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,
+and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<snapshot>
+ <required-capabilities>
+ <capability>urn:opendaylight:params:xml:ns:yang:neutronvpn:impl?module=neutronvpn-impl&revision=2015-03-25</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:mdsalutil:api?module=odl-mdsalutil&revision=2015-04-10</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:config:distributed-entity-ownership-service?module=distributed-entity-ownership-service&revision=2015-08-10</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:neutronvpn:impl">prefix:neutronvpn-impl
+ </type>
+ <name>neutronvpn-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>
+ <rpc-registry>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
+ binding:binding-rpc-registry
+ </type>
+ <name>binding-rpc-broker</name>
+ </rpc-registry>
+ <mdsalutil>
+ <type xmlns:mdsalutil="urn:opendaylight:params:xml:ns:yang:mdsalutil:api">
+ mdsalutil:odl-mdsalutil
+ </type>
+ <name>mdsalutil-service</name>
+ </mdsalutil>
+ <notification-publish-service>
+ <type xmlns:bindingimpl="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding:impl">bindingimpl:binding-new-notification-publish-service</type>
+ <name>binding-notification-publish-adapter</name>
+ </notification-publish-service>
+ <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>
+ <entity-ownership-service>
+ <type xmlns:entity-ownership="urn:opendaylight:params:xml:ns:yang:controller:md:sal:core:spi:entity-ownership-service">entity-ownership:entity-ownership-service</type>
+ <name>entity-ownership-service</name>
+ </entity-ownership-service>
+ </module>
+ </modules>
+ <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <service>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:neutronvpn:api">prefix:neutronvpn-api</type>
+ <instance>
+ <name>neutronvpn</name>
+ <provider>/modules/module[type='neutronvpn-impl'][name='neutronvpn-default']</provider>
+ </instance>
+ </service>
+ </services>
+ </data>
+ </configuration>
+</snapshot>
--- /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.neutronvpn;
+
+
+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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.bgpvpns.rev150903.bgpvpns.attributes.Bgpvpns;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.bgpvpns.rev150903.bgpvpns.attributes.bgpvpns.Bgpvpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+
+public class NeutronBgpvpnChangeListener extends AbstractDataChangeListener<Bgpvpn> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronBgpvpnChangeListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private NeutronvpnManager nvpnManager;
+
+
+ public NeutronBgpvpnChangeListener(final DataBroker db, NeutronvpnManager nVpnMgr) {
+ super(Bgpvpn.class);
+ nvpnManager = nVpnMgr;
+ registerListener(db);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("N_Bgpvpn listener Closed");
+ }
+
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(Neutron.class).child(Bgpvpns.class).child(Bgpvpn.class),
+ NeutronBgpvpnChangeListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("Neutron Manager Bgpvpn DataChange listener registration fail!", e);
+ throw new IllegalStateException("Neutron Manager Bgpvpn DataChange listener registration failed.", e);
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Bgpvpn> identifier, Bgpvpn input) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Adding Bgpvpn : key: " + identifier + ", value=" + input);
+ }
+ // Create internal VPN
+ // handle route-target
+ List<String> irt = new ArrayList<String>();
+ List<String> ert = new ArrayList<String>();
+ List<String> inrt = input.getRouteTargets();
+ List<String> inirt = input.getImportTargets();
+ List<String> inert = input.getExportTargets();
+ if (inrt != null && !inrt.isEmpty()) {
+ irt.addAll(inrt);
+ ert.addAll(inrt);
+ }
+ if (inirt != null && !inirt.isEmpty()) {
+ irt.addAll(inirt);
+ }
+ if (inert != null && !inert.isEmpty()) {
+ ert.addAll(inert);
+ }
+ List<String> rd = input.getRouteDistinguishers();
+
+ if (rd == null || rd.isEmpty()) {
+ // generate new RD
+ }
+ Uuid router = null;
+ if (input.getRouters() != null && !input.getRouters().isEmpty()) {
+ // currently only one router
+ router = input.getRouters().get(0);
+ }
+ nvpnManager.createL3Vpn(input.getUuid(), input.getName(), input.getTenantId(),
+ rd, irt, ert, router, input.getNetworks());
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Bgpvpn> identifier, Bgpvpn input) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Removing Bgpvpn : key: " + identifier + ", value=" + input);
+ }
+ nvpnManager.removeL3Vpn(input.getUuid());
+
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Bgpvpn> identifier, Bgpvpn original, Bgpvpn update) {
+ List<Uuid> oldNetworks = original.getNetworks();
+ List<Uuid> newNetworks = update.getNetworks();
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Update Bgpvpn : key: " + identifier + ", value=" + update);
+ }
+ if (newNetworks != null && !newNetworks.isEmpty()) {
+ if (oldNetworks != null && !oldNetworks.isEmpty()) {
+ if (oldNetworks != newNetworks) {
+ Iterator<Uuid> iter = newNetworks.iterator();
+ while (iter.hasNext()) {
+ Object net = iter.next();
+ if (oldNetworks.contains(net)) {
+ oldNetworks.remove(net);
+ iter.remove();
+ }
+ }
+ //clear removed networks
+ if (!oldNetworks.isEmpty()) {
+ LOG.trace("Removing old networks {} ", oldNetworks);
+ nvpnManager.dissociateNetworksFromVpn(update.getUuid(), oldNetworks);
+ }
+ //add new (Delta) Networks
+ if (!newNetworks.isEmpty()) {
+ LOG.trace("Adding delta New networks {} ", newNetworks);
+ nvpnManager.associateNetworksToVpn(update.getUuid(), newNetworks);
+ }
+ }
+ } else {
+ //add new Networks
+ LOG.trace("Adding New networks {} ", newNetworks);
+ nvpnManager.associateNetworksToVpn(update.getUuid(), newNetworks);
+ }
+ }
+ // ### TBD : Handle routers
+ }
+
+}
\ 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.neutronvpn;
+
+
+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.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.neutronvpn.api.utils.NeutronUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.Networks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanInstances;
+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.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class NeutronNetworkChangeListener extends AbstractDataChangeListener<Network> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronNetworkChangeListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private NeutronvpnManager nvpnManager;
+
+
+ public NeutronNetworkChangeListener(final DataBroker db, NeutronvpnManager nVpnMgr) {
+ super(Network.class);
+ broker = db;
+ nvpnManager = nVpnMgr;
+ registerListener(db);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("N_Network listener Closed");
+ }
+
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(Neutron.class).
+ child(Networks.class).child(Network.class),
+ NeutronNetworkChangeListener.this, DataChangeScope.SUBTREE);
+ LOG.info("Neutron Manager Network DataChange listener registration Success!");
+ } catch (final Exception e) {
+ LOG.error("Neutron Manager Network DataChange listener registration fail!", e);
+ throw new IllegalStateException("Neutron Manager Network DataChange listener registration failed.", e);
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Network> identifier, Network input) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Adding Network : key: " + identifier + ", value=" + input);
+ }
+ //Create ELAN instance for this network
+ createElanInstance(input);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Network> identifier, Network input) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Removing Network : key: " + identifier + ", value=" + input);
+ }
+ //Delete ELAN instance for this network
+ deleteElanInstance(input.getUuid().getValue());
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Network> identifier, Network original, Network update) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Updating Network : key: " + identifier + ", original value=" + original + ", update value=" +
+ update);
+ }
+ }
+
+ private void createElanInstance(Network input) {
+ String elanInstanceName = input.getUuid().getValue();
+ String segmentationId = NeutronUtils.getSegmentationIdFromNeutronNetwork(input);
+ ElanInstanceBuilder elanInstanceBuilder = new ElanInstanceBuilder().setElanInstanceName(elanInstanceName);
+ if (segmentationId != null) {
+ elanInstanceBuilder.setVni(Long.valueOf(segmentationId));
+ }
+ elanInstanceBuilder.setKey(new ElanInstanceKey(elanInstanceName));
+ ElanInstance elanInstance = elanInstanceBuilder.build();
+ InstanceIdentifier<ElanInstance> id = InstanceIdentifier.builder(ElanInstances.class)
+ .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, elanInstance);
+ }
+
+ private void deleteElanInstance(String elanInstanceName) {
+ InstanceIdentifier<ElanInstance> id = InstanceIdentifier.builder(ElanInstances.class)
+ .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, id);
+ }
+
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.neutronvpn;
+
+
+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.binding.api.NotificationPublishService;
+import org.opendaylight.controller.md.sal.binding.api.NotificationService;
+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.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.neutronvpn.api.utils.NeutronUtils;
+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.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanInterfaces;
+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.interfacemgr.rev150331.IfL2vlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlanBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.ParentRefsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.PortAddedToSubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.PortRemovedFromSubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.neutron.port.data
+ .PortFixedipToPortNameBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.Subnetmap;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+
+public class NeutronPortChangeListener extends AbstractDataChangeListener<Port> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronPortChangeListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private NeutronvpnManager nvpnManager;
+ private LockManagerService lockManager;
+ private NotificationPublishService notificationPublishService;
+ private NotificationService notificationService;
+
+
+ public NeutronPortChangeListener(final DataBroker db, NeutronvpnManager nVpnMgr,NotificationPublishService notiPublishService, NotificationService notiService) {
+ super(Port.class);
+ broker = db;
+ nvpnManager = nVpnMgr;
+ notificationPublishService = notiPublishService;
+ notificationService = notiService;
+ registerListener(db);
+ }
+
+ public void setLockManager(LockManagerService lockManager) {
+ this.lockManager = lockManager;
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("N_Port listener Closed");
+ }
+
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class),
+ NeutronPortChangeListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("Neutron Manager Port DataChange listener registration fail!", e);
+ throw new IllegalStateException("Neutron Manager Port DataChange listener registration failed.", e);
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Port> identifier, Port input) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Adding Port : key: " + identifier + ", value=" + input);
+ }
+ handleNeutronPortCreated(input);
+
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Port> identifier, Port input) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Removing Port : key: " + identifier + ", value=" + input);
+ }
+ handleNeutronPortDeleted(input);
+
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Port> identifier, Port original, Port update) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Updating Port : key: " + identifier + ", original value=" + original + ", update value=" +
+ update);
+ }
+ List<FixedIps> oldIPs = (original.getFixedIps() != null) ? original.getFixedIps() : new ArrayList<FixedIps>();
+ List<FixedIps> newIPs = (update.getFixedIps() != null) ? update.getFixedIps() : new ArrayList<FixedIps>();
+
+ if (!oldIPs.equals(newIPs)) {
+ Iterator<FixedIps> iterator = newIPs.iterator();
+ while (iterator.hasNext()) {
+ FixedIps ip = iterator.next();
+ if (oldIPs.remove(ip)) {
+ iterator.remove();
+ }
+ }
+ handleNeutronPortUpdated(original, update);
+ }
+ }
+
+ private void handleNeutronPortCreated(Port port) {
+ if (!NeutronUtils.isPortVnicTypeNormal(port)) {
+ LOG.info("Port {} is not a NORMAL VNIC Type port; OF Port interfaces are not created",
+ port.getUuid().getValue());
+ return;
+ }
+ LOG.info("Of-port-interface creation");
+ // Create of-port interface for this neutron port
+ String portInterfaceName = createOfPortInterface(port);
+ LOG.debug("Creating ELAN Interface");
+ createElanInterface(port, portInterfaceName);
+ LOG.debug("Add port to subnet");
+ // add port to local Subnets DS
+ Uuid vpnId = addPortToSubnets(port);
+
+ if (vpnId != null) {
+ // create vpn-interface on this neutron port
+ LOG.debug("Adding VPN Interface");
+ nvpnManager.createVpnInterface(vpnId, port);
+ Uuid routerId = NeutronvpnUtils.getVpnMap(broker, vpnId).getRouterId();
+ if(routerId != null) {
+ nvpnManager.addToNeutronRouterInterfacesMap(routerId, port.getUuid().getValue());
+ }
+ }
+ }
+
+ private void handleNeutronPortDeleted(Port port) {
+ LOG.debug("Of-port-interface removal");
+ LOG.debug("Remove port from subnet");
+ // remove port from local Subnets DS
+ Uuid vpnId = removePortFromSubnets(port);
+
+ if (vpnId != null) {
+ // remove vpn-interface for this neutron port
+ LOG.debug("removing VPN Interface");
+ nvpnManager.deleteVpnInterface(port);
+ }
+ // Remove of-port interface for this neutron port
+ // ELAN interface is also implicitly deleted as part of this operation
+ deleteOfPortInterface(port);
+
+ Uuid routerId = NeutronvpnUtils.getVpnMap(broker, vpnId).getRouterId();
+ if(routerId != null) {
+ nvpnManager.removeFromNeutronRouterInterfacesMap(routerId, port.getUuid().getValue());
+ }
+
+ }
+
+ private void handleNeutronPortUpdated(Port portoriginal, Port portupdate) {
+ LOG.debug("Add port to subnet");
+ // add port FixedIP to local Subnets DS
+ Uuid vpnIdup = addPortToSubnets(portupdate);
+
+ if (vpnIdup != null) {
+ nvpnManager.createVpnInterface(vpnIdup, portupdate);
+ Uuid routerId = NeutronvpnUtils.getVpnMap(broker, vpnIdup).getRouterId();
+ if(routerId != null) {
+ nvpnManager.addToNeutronRouterInterfacesMap(routerId, portupdate.getUuid().getValue());
+ }
+ }
+
+ // remove port FixedIP from local Subnets DS
+ Uuid vpnIdor = removePortFromSubnets(portoriginal);
+
+ if (vpnIdor != null) {
+ nvpnManager.deleteVpnInterface(portoriginal);
+ Uuid routerId = NeutronvpnUtils.getVpnMap(broker, vpnIdor).getRouterId();
+ if(routerId != null) {
+ nvpnManager.removeFromNeutronRouterInterfacesMap(routerId, portoriginal.getUuid().getValue());
+ }
+ }
+ }
+
+ private String createOfPortInterface(Port port) {
+ Interface inf = createInterface(port);
+ String infName = inf.getName();
+
+ LOG.debug("Creating OFPort Interface {}", infName);
+ InstanceIdentifier interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(infName);
+ try {
+ Optional<Interface> optionalInf = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
+ interfaceIdentifier);
+ if (!optionalInf.isPresent()) {
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, interfaceIdentifier, inf);
+ } else {
+ LOG.error("Interface {} is already present", infName);
+ }
+ } catch (Exception e) {
+ LOG.error("failed to create interface {} due to the exception {} ", infName, e.getMessage());
+ }
+ return infName;
+ }
+
+ private Interface createInterface(Port port) {
+ String parentRefName = NeutronvpnUtils.uuidToTapPortName(port.getUuid());;
+ String interfaceName = port.getUuid().getValue();
+ IfL2vlan.L2vlanMode l2VlanMode = IfL2vlan.L2vlanMode.Trunk;
+ InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
+ IfL2vlanBuilder ifL2vlanBuilder = new IfL2vlanBuilder();
+ ifL2vlanBuilder.setL2vlanMode(l2VlanMode);
+ ParentRefsBuilder parentRefsBuilder = new ParentRefsBuilder().setParentInterface(parentRefName);
+ interfaceBuilder.setEnabled(true).setName(interfaceName).setType(L2vlan.class).addAugmentation(IfL2vlan
+ .class, ifL2vlanBuilder.build()).addAugmentation(ParentRefs.class, parentRefsBuilder.build());
+ return interfaceBuilder.build();
+ }
+
+ private void deleteOfPortInterface(Port port) {
+ String name = port.getUuid().getValue();
+ LOG.debug("Removing OFPort Interface {}", name);
+ InstanceIdentifier interfaceIdentifier = NeutronvpnUtils.buildVlanInterfaceIdentifier(name);
+ try {
+ Optional<Interface> optionalInf = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
+ interfaceIdentifier);
+ if (optionalInf.isPresent()) {
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, interfaceIdentifier);
+ } else {
+ LOG.error("Interface {} is not present", name);
+ }
+ } catch (Exception e) {
+ LOG.error("Failed to delete interface {} due to the exception {}", name, e.getMessage());
+ }
+ }
+
+ private void createElanInterface(Port port, String name) {
+ String elanInstanceName = port.getNetworkId().getValue();
+ List<PhysAddress> physAddresses = new ArrayList<>();
+ physAddresses.add(new PhysAddress(port.getMacAddress()));
+
+ InstanceIdentifier<ElanInterface> id = InstanceIdentifier.builder(ElanInterfaces.class).child(ElanInterface
+ .class, new ElanInterfaceKey(name)).build();
+ ElanInterface elanInterface = new ElanInterfaceBuilder().setElanInstanceName(elanInstanceName)
+ .setName(name).setStaticMacEntries(physAddresses).setKey(new ElanInterfaceKey(name)).build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, elanInterface);
+ LOG.debug("Creating new ELan Interface {}", elanInterface);
+ }
+
+ // adds port to subnet list and creates vpnInterface
+ private Uuid addPortToSubnets(Port port) {
+ Uuid subnetId = null;
+ Uuid vpnId = null;
+ Subnetmap subnetmap = null;
+ String infName = port.getUuid().getValue();
+ boolean isLockAcquired = false;
+ String lockName = port.getUuid().getValue();
+
+ // find the subnet to which this port is associated
+ FixedIps ip = port.getFixedIps().get(0);
+ String ipValue = ip.getIpAddress().getIpv4Address().getValue();
+ InstanceIdentifier id = NeutronvpnUtils.buildFixedIpToPortNameIdentifier(ipValue);
+ PortFixedipToPortNameBuilder builder = new PortFixedipToPortNameBuilder().setPortFixedip(ipValue)
+ .setPortName(infName);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, builder.build());
+ LOG.debug("fixedIp-name map for neutron port with fixedIp: {}, name: {} added to NeutronPortData DS",
+ ipValue, infName);
+ subnetId = ip.getSubnetId();
+ subnetmap = nvpnManager.updateSubnetNode(subnetId, null, null, null, null, null, port.getUuid());
+ if (subnetmap != null) {
+ vpnId = subnetmap.getVpnId();
+ }
+ if(vpnId != null) {
+ try {
+ isLockAcquired = NeutronvpnUtils.lock(lockManager, lockName);
+ checkAndPublishPortAddNotification(subnetmap.getSubnetIp(), subnetId, port.getUuid());
+ LOG.debug("Port added to subnet notification sent");
+ } catch (Exception e) {
+ LOG.error("Port added to subnet notification failed", e);
+ } finally {
+ if (isLockAcquired) {
+ NeutronvpnUtils.unlock(lockManager, lockName);
+ }
+ }
+ }
+ return vpnId;
+ }
+
+ private Uuid removePortFromSubnets(Port port) {
+ Uuid subnetId = null;
+ Uuid vpnId = null;
+ Subnetmap subnetmap = null;
+ boolean isLockAcquired = false;
+ String lockName = port.getUuid().getValue();
+
+ // find the subnet to which this port is associated
+ FixedIps ip = port.getFixedIps().get(0);
+ String ipValue = ip.getIpAddress().getIpv4Address().getValue();
+ InstanceIdentifier id = NeutronvpnUtils.buildFixedIpToPortNameIdentifier(ipValue);
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, id);
+ LOG.debug("fixedIp-name map for neutron port with fixedIp: {} deleted from NeutronPortData DS", ipValue);
+ subnetId = ip.getSubnetId();
+ subnetmap = nvpnManager.removeFromSubnetNode(subnetId, null, null, null, port.getUuid());
+ if (subnetmap != null) {
+ vpnId = subnetmap.getVpnId();
+ }
+ if(vpnId != null) {
+ try {
+ isLockAcquired = NeutronvpnUtils.lock(lockManager, lockName);
+ checkAndPublishPortRemoveNotification(subnetmap.getSubnetIp(), subnetId, port.getUuid());
+ LOG.debug("Port removed from subnet notification sent");
+ } catch (Exception e) {
+ LOG.error("Port removed from subnet notification failed", e);
+ } finally {
+ if (isLockAcquired) {
+ NeutronvpnUtils.unlock(lockManager, lockName);
+ }
+ }
+ }
+ return vpnId;
+ }
+
+ private void checkAndPublishPortAddNotification(String subnetIp, Uuid subnetId, Uuid portId)throws InterruptedException{
+ PortAddedToSubnetBuilder builder = new PortAddedToSubnetBuilder();
+
+ LOG.info("publish notification called");
+
+ builder.setSubnetIp(subnetIp);
+ builder.setSubnetId(subnetId);
+ builder.setPortId(portId);
+
+ notificationPublishService.putNotification(builder.build());
+ }
+
+ private void checkAndPublishPortRemoveNotification(String subnetIp, Uuid subnetId, Uuid portId)throws InterruptedException{
+ PortRemovedFromSubnetBuilder builder = new PortRemovedFromSubnetBuilder();
+
+ LOG.info("publish notification called");
+
+ builder.setPortId(portId);
+ builder.setSubnetIp(subnetIp);
+ builder.setSubnetId(subnetId);
+
+ notificationPublishService.putNotification(builder.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.neutronvpn;
+
+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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.router.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+
+public class NeutronRouterChangeListener extends AbstractDataChangeListener<Router> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronRouterChangeListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private NeutronvpnManager nvpnManager;
+
+
+ public NeutronRouterChangeListener(final DataBroker db, NeutronvpnManager nVpnMgr) {
+ super(Router.class);
+ broker = db;
+ nvpnManager = nVpnMgr;
+ registerListener(db);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("N_Router listener Closed");
+ }
+
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(Neutron.class).child(Routers.class).child(Router.class),
+ NeutronRouterChangeListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("Neutron Manager Router DataChange listener registration fail!", e);
+ throw new IllegalStateException("Neutron Manager Router DataChange listener registration failed.", e);
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Router> identifier, Router input) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Adding Router : key: " + identifier + ", value=" + input);
+ }
+ // Create internal VPN
+ nvpnManager.createL3Vpn(input.getUuid(), null, null, null, null, null, input.getUuid(), null);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Router> identifier, Router input) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Removing router : key: " + identifier + ", value=" + input);
+ }
+ Uuid routerId = input.getUuid();
+ // fetch subnets associated to router
+ List<Interfaces> routerInterfaces = input.getInterfaces();
+ List<Uuid> routerSubnetIds = new ArrayList<Uuid>();
+ if (routerInterfaces != null) {
+ for (Interfaces rtrIf : routerInterfaces) {
+ routerSubnetIds.add(rtrIf.getSubnetId());
+ }
+ }
+ nvpnManager.handleNeutronRouterDeleted(routerId, routerSubnetIds);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Router> identifier, Router original, Router update) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Updating Router : key: " + identifier + ", original value=" + original + ", update value=" +
+ update);
+ }
+ Uuid routerId = update.getUuid();
+ Uuid vpnId = NeutronvpnUtils.getVpnForRouter(broker, routerId, true);
+ // internal vpn always present in case external vpn not found
+ if (vpnId == null) {
+ vpnId = routerId;
+ }
+ List<Interfaces> oldInterfaces = (original.getInterfaces() != null) ? original.getInterfaces() : new
+ ArrayList<Interfaces>();
+ List<Interfaces> newInterfaces = (update.getInterfaces() != null) ? update.getInterfaces() : new
+ ArrayList<Interfaces>();
+ List<Routes> oldRoutes = (original.getRoutes() != null) ? original.getRoutes() : new ArrayList<Routes>();
+ List<Routes> newRoutes = (update.getRoutes() != null) ? update.getRoutes() : new ArrayList<Routes>();
+ if (!oldInterfaces.equals(newInterfaces)) {
+ for (Interfaces intrf : newInterfaces) {
+ if (!oldInterfaces.remove(intrf)) {
+ // add new subnet
+ nvpnManager.addSubnetToVpn(vpnId, intrf.getSubnetId());
+ }
+ }
+ //clear remaining old subnets
+ for (Interfaces intrf : oldInterfaces) {
+ nvpnManager.removeSubnetFromVpn(vpnId, intrf.getSubnetId());
+ }
+ }
+ if (!oldRoutes.equals(newRoutes)) {
+ Iterator<Routes> iterator = newRoutes.iterator();
+ while (iterator.hasNext()) {
+ Routes route = iterator.next();
+ if (oldRoutes.remove(route)) {
+ iterator.remove();
+ }
+ }
+ nvpnManager.addAdjacencyforExtraRoute(newRoutes, true, null);
+ if (!oldRoutes.isEmpty()) {
+ nvpnManager.removeAdjacencyforExtraRoute(oldRoutes);
+ }
+ }
+ }
+}
--- /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.neutronvpn;
+
+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.mdsalutil.MDSALUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.networkmaps.NetworkMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.networkmaps.NetworkMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.networkmaps.NetworkMapKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class NeutronSubnetChangeListener extends AbstractDataChangeListener<Subnet> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronSubnetChangeListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private NeutronvpnManager nvpnManager;
+
+
+ public NeutronSubnetChangeListener(final DataBroker db, NeutronvpnManager nVpnMgr) {
+ super(Subnet.class);
+ broker = db;
+ nvpnManager = nVpnMgr;
+ registerListener(db);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("N_Subnet listener Closed");
+ }
+
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(Neutron.class).child(Subnets.class).child(Subnet.class),
+ NeutronSubnetChangeListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("Neutron Manager Subnet DataChange listener registration fail!", e);
+ throw new IllegalStateException("Neutron Manager Subnet DataChange listener registration failed.", e);
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Subnet> identifier, Subnet input) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Adding Subnet : key: " + identifier + ", value=" + input);
+ }
+ handleNeutronSubnetCreated(input.getUuid(), input.getCidr(), input.getNetworkId(), input.getTenantId());
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Subnet> identifier, Subnet input) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Removing subnet : key: " + identifier + ", value=" + input);
+ }
+ handleNeutronSubnetDeleted(input.getUuid(), input.getNetworkId(), null);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Subnet> identifier, Subnet original, Subnet update) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Updating Subnet : key: " + identifier + ", original value=" + original + ", update value=" +
+ update);
+ }
+ handleNeutronSubnetUpdated(update.getUuid(), update.getNetworkId(), update.getTenantId());
+ }
+
+ private void handleNeutronSubnetCreated(Uuid subnetId, String subnetIp, Uuid networkId, Uuid tenantId) {
+ nvpnManager.updateSubnetNode(subnetId, subnetIp, tenantId, networkId, null, null, null);
+ if (networkId != null && NeutronvpnUtils.getNeutronNetwork(broker, networkId) != null) {
+ createSubnetToNetworkMapping(subnetId, networkId);
+ }
+ }
+
+ private void handleNeutronSubnetDeleted(Uuid subnetId, Uuid networkId, Uuid tenantId) {
+ Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(broker, networkId);
+ if (vpnId != null) {
+ nvpnManager.removeSubnetFromVpn(vpnId, subnetId);
+ }
+ if (networkId != null) {
+ deleteSubnetToNetworkMapping(subnetId, networkId);
+ }
+ nvpnManager.deleteSubnetMapNode(subnetId);
+ }
+
+ private void handleNeutronSubnetUpdated(Uuid subnetId, Uuid networkId, Uuid tenantId) {
+ Uuid oldNetworkId = NeutronvpnUtils.getSubnetmap(broker, subnetId).getNetworkId();
+ if (oldNetworkId != null && !oldNetworkId.equals(networkId)) {
+ deleteSubnetToNetworkMapping(subnetId, oldNetworkId);
+ }
+ if (networkId != null && !networkId.equals(oldNetworkId)) {
+ createSubnetToNetworkMapping(subnetId, networkId);
+ }
+ nvpnManager.updateSubnetNode(subnetId, null, tenantId, networkId, null, null, null);
+ }
+
+ private void createSubnetToNetworkMapping(Uuid subnetId, Uuid networkId) {
+ try {
+ InstanceIdentifier networkMapIdentifier = NeutronvpnUtils.buildNetworkMapIdentifier(networkId);
+ Optional<NetworkMap> optionalNetworkMap = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
+ networkMapIdentifier);
+ NetworkMapBuilder nwMapBuilder = null;
+ if (optionalNetworkMap.isPresent()) {
+ nwMapBuilder = new NetworkMapBuilder(optionalNetworkMap.get());
+ } else {
+ nwMapBuilder = new NetworkMapBuilder().setKey(new NetworkMapKey(networkId)).setNetworkId(networkId);
+ LOG.debug("Adding a new network node in NetworkMaps DS for network {}", networkId.getValue());
+ }
+ List<Uuid> subnetIdList = nwMapBuilder.getSubnetIdList();
+ if (subnetIdList == null) {
+ subnetIdList = new ArrayList<>();
+ }
+ subnetIdList.add(subnetId);
+ nwMapBuilder.setSubnetIdList(subnetIdList);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier, nwMapBuilder.build());
+ LOG.debug("Created subnet-network mapping for subnet {} network {}", subnetId.getValue(),
+ networkId.getValue());
+ } catch (Exception e) {
+ LOG.error("Create subnet-network mapping failed for subnet {} network {}", subnetId.getValue(),
+ networkId.getValue());
+ }
+ }
+
+ private void deleteSubnetToNetworkMapping(Uuid subnetId, Uuid networkId) {
+ try {
+ InstanceIdentifier networkMapIdentifier = NeutronvpnUtils.buildNetworkMapIdentifier(networkId);
+ Optional<NetworkMap> optionalNetworkMap = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
+ networkMapIdentifier);
+ if (optionalNetworkMap.isPresent()) {
+ NetworkMapBuilder nwMapBuilder = new NetworkMapBuilder(optionalNetworkMap.get());
+ List<Uuid> subnetIdList = nwMapBuilder.getSubnetIdList();
+ if (subnetIdList.remove(subnetId)) {
+ if (subnetIdList.size() == 0) {
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier);
+ LOG.debug("Deleted network node in NetworkMaps DS for network {}", subnetId.getValue(),
+ networkId.getValue());
+ } else {
+ nwMapBuilder.setSubnetIdList(subnetIdList);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, networkMapIdentifier,
+ nwMapBuilder.build());
+ LOG.debug("Deleted subnet-network mapping for subnet {} network {}", subnetId.getValue(),
+ networkId.getValue());
+ }
+ } else {
+ LOG.error("Subnet {} is not mapped to network {}", subnetId.getValue(), networkId.getValue());
+ }
+ } else {
+ LOG.error("network {} not present for subnet {} ", networkId, subnetId);
+ }
+ } catch (Exception e) {
+ LOG.error("Delete subnet-network mapping failed for subnet {} network {}", subnetId.getValue(),
+ networkId.getValue());
+ }
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.neutronvpn;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.SettableFuture;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.md.sal.binding.api.NotificationService;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargetsBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets
+ .VpnTargetBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
+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.VpnInstanceBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance
+ .Ipv4FamilyBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
+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.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacenciesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.RouterInterfacesMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.router.interfaces.map.RouterInterfacesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.router.interfaces.map.router.interfaces.InterfacesKey;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.l3.attributes.Routes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanInstances;
+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.lockmanager.rev150819.LockManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.createl3vpn.input.L3vpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.getl3vpn.output.L3vpnInstances;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.getl3vpn.output
+ .L3vpnInstancesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.Subnetmap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.vpnmaps.VpnMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.vpnmaps.VpnMapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.vpnmaps.VpnMapKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import java.util.EventListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class NeutronvpnManager implements NeutronvpnService, AutoCloseable , EventListener{
+
+ private static final Logger logger = LoggerFactory.getLogger(NeutronvpnManager.class);
+ private final DataBroker broker;
+ private LockManagerService lockManager;
+ IMdsalApiManager mdsalUtil;
+ private NotificationPublishService notificationPublishService;
+ private NotificationService notificationService;
+ Boolean isExternalVpn;
+
+ /**
+ * @param db - dataBroker reference
+ * @param mdsalManager - MDSAL Util API access
+ */
+ public NeutronvpnManager(final DataBroker db, IMdsalApiManager mdsalManager,NotificationPublishService notiPublishService,
+ NotificationService notiService) {
+ broker = db;
+ mdsalUtil = mdsalManager;
+ notificationPublishService = notiPublishService;
+ notificationService = notiService;
+ }
+
+ public void setLockManager(LockManagerService lockManager) {
+ this.lockManager = lockManager;
+ }
+
+ @Override
+ public void close() throws Exception {
+ logger.info("Neutron VPN Manager Closed");
+ }
+
+ protected Subnetmap updateSubnetNode(Uuid subnetId, String subnetIp, Uuid tenantId, Uuid networkId, Uuid routerId,
+ Uuid vpnId, Uuid portId) {
+ Subnetmap subnetmap = null;
+ SubnetmapBuilder builder = null;
+ boolean isLockAcquired = false;
+ InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).
+ child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
+ try {
+ Optional<Subnetmap> sn = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION, id);
+ logger.debug("updating Subnet :read: ");
+ if (sn.isPresent()) {
+ builder = new SubnetmapBuilder(sn.get());
+ logger.debug("updating Subnet :existing: ");
+ } else {
+ builder = new SubnetmapBuilder().setKey(new SubnetmapKey(subnetId)).setId(subnetId);
+ logger.debug("updating Subnet :new: ");
+ }
+
+ if (subnetIp != null) {
+ builder.setSubnetIp(subnetIp);
+ }
+ if (routerId != null) {
+ builder.setRouterId(routerId);
+ }
+ if (networkId != null) {
+ builder.setNetworkId(networkId);
+ }
+ if (vpnId != null) {
+ builder.setVpnId(vpnId);
+ }
+ if (tenantId != null) {
+ builder.setTenantId(tenantId);
+ }
+
+ if (portId != null) {
+ List<Uuid> portList = builder.getPortList();
+ if (portList == null) {
+ portList = new ArrayList<Uuid>();
+ }
+ portList.add(portId);
+ builder.setPortList(portList);
+ }
+
+ subnetmap = builder.build();
+ isLockAcquired = NeutronvpnUtils.lock(lockManager, subnetId.getValue());
+ logger.debug("Creating/Updating subnetMap node: {} ", subnetId.getValue());
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
+ } catch (Exception e) {
+ logger.error("Updation of subnetMap failed for node: {}", subnetId.getValue());
+ } finally {
+ if (isLockAcquired) {
+ NeutronvpnUtils.unlock(lockManager, subnetId.getValue());
+ }
+ }
+ return subnetmap;
+ }
+
+ protected Subnetmap removeFromSubnetNode(Uuid subnetId, Uuid networkId, Uuid routerId, Uuid vpnId, Uuid portId) {
+ Subnetmap subnetmap = null;
+ boolean isLockAcquired = false;
+ InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).
+ child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
+ try {
+ Optional<Subnetmap> sn = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION, id);
+ if (sn.isPresent()) {
+ SubnetmapBuilder builder = new SubnetmapBuilder(sn.get());
+ if (routerId != null) {
+ builder.setRouterId(null);
+ }
+ if (networkId != null) {
+ builder.setNetworkId(null);
+ }
+ if (vpnId != null) {
+ builder.setVpnId(null);
+ }
+ if (portId != null && builder.getPortList() != null) {
+ List<Uuid> portList = builder.getPortList();
+ portList.remove(portId);
+ builder.setPortList(portList);
+ }
+
+ subnetmap = builder.build();
+ isLockAcquired = NeutronvpnUtils.lock(lockManager, subnetId.getValue());
+ logger.debug("Removing from existing subnetmap node: {} ", subnetId.getValue());
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, subnetmap);
+ } else {
+ logger.warn("removing from non-existing subnetmap node: {} ", subnetId.getValue());
+ }
+ } catch (Exception e) {
+ logger.error("Removal from subnetmap failed for node: {}", subnetId.getValue());
+ } finally {
+ if (isLockAcquired) {
+ NeutronvpnUtils.unlock(lockManager, subnetId.getValue());
+ }
+ }
+ return subnetmap;
+ }
+
+ protected void deleteSubnetMapNode(Uuid subnetId) {
+ boolean isLockAcquired = false;
+ InstanceIdentifier<Subnetmap> subnetMapIdentifier = InstanceIdentifier.builder(Subnetmaps.class)
+ .child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
+ logger.debug("removing subnetMap node: {} ", subnetId.getValue());
+ try {
+ isLockAcquired = NeutronvpnUtils.lock(lockManager, subnetId.getValue());
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, subnetMapIdentifier);
+ } catch (Exception e) {
+ logger.error("Delete subnetMap node failed for subnet : {} ", subnetId.getValue());
+ } finally {
+ if (isLockAcquired) {
+ NeutronvpnUtils.unlock(lockManager, subnetId.getValue());
+ }
+ }
+ }
+
+ private void updateVpnInstanceNode(String vpnName, List<String> rd, List<String> irt, List<String> ert) {
+
+ VpnInstanceBuilder builder = null;
+ List<VpnTarget> vpnTargetList = new ArrayList<VpnTarget>();
+ boolean isLockAcquired = false;
+ InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class).
+ child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
+ try {
+ Optional<VpnInstance> optionalVpn = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
+ vpnIdentifier);
+ logger.debug("Creating/Updating a new vpn-instance node: {} ", vpnName);
+ if (optionalVpn.isPresent()) {
+ builder = new VpnInstanceBuilder(optionalVpn.get());
+ logger.debug("updating existing vpninstance node");
+ } else {
+ builder = new VpnInstanceBuilder().setKey(new VpnInstanceKey(vpnName)).setVpnInstanceName(vpnName);
+ }
+ if (irt != null && !irt.isEmpty()) {
+ if (ert != null && !ert.isEmpty()) {
+ List<String> commonRT = new ArrayList<String>(irt);
+ commonRT.retainAll(ert);
+
+ for (String common : commonRT) {
+ irt.remove(common);
+ ert.remove(common);
+ VpnTarget vpnTarget = new VpnTargetBuilder().setKey(new VpnTargetKey(common)).setVrfRTValue
+ (common).setVrfRTType(VpnTarget.VrfRTType.Both).build();
+ vpnTargetList.add(vpnTarget);
+ }
+ }
+ for (String importRT : irt) {
+ VpnTarget vpnTarget = new VpnTargetBuilder().setKey(new VpnTargetKey(importRT)).setVrfRTValue
+ (importRT).setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
+ vpnTargetList.add(vpnTarget);
+ }
+ }
+
+ if (ert != null && !ert.isEmpty()) {
+ for (String exportRT : ert) {
+ VpnTarget vpnTarget = new VpnTargetBuilder().setKey(new VpnTargetKey(exportRT)).setVrfRTValue
+ (exportRT).setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
+ vpnTargetList.add(vpnTarget);
+ }
+ }
+
+ VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
+
+ Ipv4FamilyBuilder ipv4vpnBuilder = new Ipv4FamilyBuilder().setVpnTargets(vpnTargets);
+
+ if (rd != null && !rd.isEmpty()) {
+ ipv4vpnBuilder.setRouteDistinguisher(rd.get(0));
+ }
+
+ VpnInstance newVpn = builder.setIpv4Family(ipv4vpnBuilder.build()).build();
+ isLockAcquired = NeutronvpnUtils.lock(lockManager, vpnName);
+ logger.debug("Creating/Updating vpn-instance for {} ", vpnName);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier, newVpn);
+ } catch (Exception e) {
+ logger.error("Update VPN Instance node failed for node: {} {} {} {}", vpnName, rd, irt, ert);
+ } finally {
+ if (isLockAcquired) {
+ NeutronvpnUtils.unlock(lockManager, vpnName);
+ }
+ }
+ }
+
+ private void deleteVpnMapsNode(Uuid vpnid) {
+ boolean isLockAcquired = false;
+ InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
+ .child(VpnMap.class, new VpnMapKey(vpnid)).build();
+ logger.debug("removing vpnMaps node: {} ", vpnid.getValue());
+ try {
+ isLockAcquired = NeutronvpnUtils.lock(lockManager, vpnid.getValue());
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
+ } catch (Exception e) {
+ logger.error("Delete vpnMaps node failed for vpn : {} ", vpnid.getValue());
+ } finally {
+ if (isLockAcquired) {
+ NeutronvpnUtils.unlock(lockManager, vpnid.getValue());
+ }
+ }
+ }
+
+ private void updateVpnMaps(Uuid vpnId, String name, Uuid router, Uuid tenantId, List<Uuid> networks) {
+ VpnMapBuilder builder;
+ boolean isLockAcquired = false;
+ InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
+ .child(VpnMap.class, new VpnMapKey(vpnId)).build();
+ try {
+ Optional<VpnMap> optionalVpnMap = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
+ vpnMapIdentifier);
+ if (optionalVpnMap.isPresent()) {
+ builder = new VpnMapBuilder(optionalVpnMap.get());
+ } else {
+ builder = new VpnMapBuilder().setKey(new VpnMapKey(vpnId)).setVpnId(vpnId);
+ }
+
+ if (name != null) {
+ builder.setName(name);
+ }
+ if (tenantId != null) {
+ builder.setTenantId(tenantId);
+ }
+ if (router != null) {
+ builder.setRouterId(router);
+ }
+ if (networks != null) {
+ List<Uuid> nwList = builder.getNetworkIds();
+ if (nwList == null) {
+ nwList = new ArrayList<Uuid>();
+ }
+ nwList.addAll(networks);
+ builder.setNetworkIds(nwList);
+ }
+
+ isLockAcquired = NeutronvpnUtils.lock(lockManager, vpnId.getValue());
+ logger.debug("Creating/Updating vpnMaps node: {} ", vpnId.getValue());
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier, builder.build());
+ logger.debug("VPNMaps DS updated for VPN {} ", vpnId.getValue());
+ } catch (Exception e) {
+ logger.error("UpdateVpnMaps failed for node: {} ", vpnId.getValue());
+ } finally {
+ if (isLockAcquired) {
+ NeutronvpnUtils.unlock(lockManager, vpnId.getValue());
+ }
+ }
+ }
+
+ private void clearFromVpnMaps(Uuid vpnId, Uuid routerId, List<Uuid> networkIds) {
+ boolean isLockAcquired = false;
+ InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
+ .child(VpnMap.class, new VpnMapKey(vpnId)).build();
+ Optional<VpnMap> optionalVpnMap = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
+ vpnMapIdentifier);
+ if (optionalVpnMap.isPresent()) {
+ VpnMap vpnMap = optionalVpnMap.get();
+ VpnMapBuilder vpnMapBuilder = new VpnMapBuilder(vpnMap);
+ if (routerId != null) {
+ if (vpnMap.getNetworkIds() == null && routerId.equals(vpnMap.getVpnId())) {
+ try {
+ // remove entire node in case of internal VPN
+ isLockAcquired = NeutronvpnUtils.lock(lockManager, vpnId.getValue());
+ logger.debug("removing vpnMaps node: {} ", vpnId);
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
+ } catch (Exception e) {
+ logger.error("Deletion of vpnMaps node failed for vpn {}", vpnId.getValue());
+ } finally {
+ if (isLockAcquired) {
+ NeutronvpnUtils.unlock(lockManager, vpnId.getValue());
+ }
+ }
+ return;
+ }
+ vpnMapBuilder.setRouterId(null);
+ }
+ if (networkIds != null) {
+ List<Uuid> vpnNw = vpnMap.getNetworkIds();
+ for (Uuid nw : networkIds) {
+ vpnNw.remove(nw);
+ }
+ if (vpnNw.isEmpty()) {
+ logger.debug("setting networks null in vpnMaps node: {} ", vpnId.getValue());
+ vpnMapBuilder.setNetworkIds(null);
+ } else {
+ vpnMapBuilder.setNetworkIds(vpnNw);
+ }
+ }
+
+ try {
+ isLockAcquired = NeutronvpnUtils.lock(lockManager, vpnId.getValue());
+ logger.debug("clearing from vpnMaps node: {} ", vpnId.getValue());
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier, vpnMapBuilder.build
+ ());
+ } catch (Exception e) {
+ logger.error("Clearing from vpnMaps node failed for vpn {}", vpnId.getValue());
+ } finally {
+ if (isLockAcquired) {
+ NeutronvpnUtils.unlock(lockManager, vpnId.getValue());
+ }
+ }
+ } else {
+ logger.error("VPN : {} not found", vpnId.getValue());
+ }
+ logger.debug("Clear from VPNMaps DS successful for VPN {} ", vpnId.getValue());
+ }
+
+ private void deleteVpnInstance(Uuid vpnId) {
+ boolean isLockAcquired = false;
+ InstanceIdentifier<VpnInstance> vpnIdentifier = InstanceIdentifier.builder(VpnInstances.class).
+ child(VpnInstance.class, new VpnInstanceKey(vpnId.getValue())).build();
+ try {
+ isLockAcquired = NeutronvpnUtils.lock(lockManager, vpnId.getValue());
+ logger.debug("Deleting vpnInstance {}", vpnId.getValue());
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
+ } catch (Exception e) {
+ logger.error("Deletion of VPNInstance node failed for VPN {}", vpnId.getValue());
+ } finally {
+ if (isLockAcquired) {
+ NeutronvpnUtils.unlock(lockManager, vpnId.getValue());
+ }
+ }
+ }
+
+ protected void createVpnInterface(Uuid vpnId, Port port) {
+ boolean isLockAcquired = false;
+ if (vpnId == null || port == null) {
+ return;
+ }
+ String infName = port.getUuid().getValue();
+ List<Adjacency> adjList = new ArrayList<Adjacency>();
+ InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
+
+ // find router associated to vpn
+ Uuid routerId = NeutronvpnUtils.getRouterforVpn(broker, vpnId);
+ Router rtr = null;
+ if (routerId != null) {
+ rtr = NeutronvpnUtils.getNeutronRouter(broker, routerId);
+ }
+ // find all subnets to which this port is associated
+ List<FixedIps> ips = port.getFixedIps();
+ // create adjacency list
+ for (FixedIps ip : ips) {
+ // create vm adjacency
+ StringBuilder IpPrefixBuild = new StringBuilder(ip.getIpAddress().getIpv4Address().getValue());
+ String IpPrefix = IpPrefixBuild.append("/32").toString();
+ Adjacency vmAdj = new AdjacencyBuilder().setKey(new AdjacencyKey(IpPrefix)).setIpAddress(IpPrefix)
+ .setMacAddress(port.getMacAddress()).build();
+ adjList.add(vmAdj);
+ // create extra route adjacency
+ if (rtr != null && rtr.getRoutes() != null) {
+ List<Routes> routeList = rtr.getRoutes();
+ List<Adjacency> erAdjList = addAdjacencyforExtraRoute(routeList, false, infName);
+ if (erAdjList != null && !erAdjList.isEmpty()) {
+ adjList.addAll(erAdjList);
+ }
+ }
+ }
+ // create vpn-interface on this neutron port
+ Adjacencies adjs = new AdjacenciesBuilder().setAdjacency(adjList).build();
+ VpnInterfaceBuilder vpnb = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName)).
+ setName(infName).setVpnInstanceName(vpnId.getValue()).addAugmentation(Adjacencies.class, adjs);
+ VpnInterface vpnIf = vpnb.build();
+
+ try {
+ isLockAcquired = NeutronvpnUtils.lock(lockManager, infName);
+ logger.debug("Creating vpn interface {}", vpnIf);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
+ } catch (Exception ex) {
+ logger.error("Creation of vpninterface {} failed due to {}", infName, ex);
+ } finally {
+ if (isLockAcquired) {
+ NeutronvpnUtils.unlock(lockManager, infName);
+ }
+ }
+ }
+
+ protected void deleteVpnInterface(Port port) {
+
+ if (port != null) {
+ boolean isLockAcquired = false;
+ String infName = port.getUuid().getValue();
+ InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
+
+ try {
+ isLockAcquired = NeutronvpnUtils.lock(lockManager, infName);
+ logger.debug("Deleting vpn interface {}", infName);
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier);
+ } catch (Exception ex) {
+ logger.error("Deletion of vpninterface {} failed due to {}", infName, ex);
+ } finally {
+ if (isLockAcquired) {
+ NeutronvpnUtils.unlock(lockManager, infName);
+ }
+ }
+ }
+ }
+
+ protected void updateVpnInterface(Uuid vpnId, Port port) {
+ if (vpnId == null || port == null) {
+ return;
+ }
+ boolean isLockAcquired = false;
+ String infName = port.getUuid().getValue();
+ InstanceIdentifier<VpnInterface> vpnIfIdentifier = NeutronvpnUtils.buildVpnInterfaceIdentifier(infName);
+ try {
+ Optional<VpnInterface> optionalVpnInterface = NeutronvpnUtils.read(broker, LogicalDatastoreType
+ .CONFIGURATION, vpnIfIdentifier);
+ if (optionalVpnInterface.isPresent()) {
+ VpnInterfaceBuilder vpnIfBuilder = new VpnInterfaceBuilder(optionalVpnInterface.get());
+ VpnInterface vpnIf = vpnIfBuilder.setVpnInstanceName(vpnId.getValue()).build();
+ isLockAcquired = NeutronvpnUtils.lock(lockManager, infName);
+ logger.debug("Updating vpn interface {}", vpnIf);
+ MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
+ } else {
+ logger.error("VPN Interface {} not found", infName);
+ }
+ } catch (Exception ex) {
+ logger.error("Updation of vpninterface {} failed due to {}", infName, ex);
+ } finally {
+ if (isLockAcquired) {
+ NeutronvpnUtils.unlock(lockManager, infName);
+ }
+ }
+ }
+
+ public void createL3Vpn(Uuid vpn, String name, Uuid tenant, List<String> rd, List<String> irt, List<String> ert,
+ Uuid router, List<Uuid> networks) {
+
+ // Update VPN Instance node
+ updateVpnInstanceNode(vpn.getValue(), rd, irt, ert);
+
+ // Update local vpn-subnet DS
+ updateVpnMaps(vpn, name, router, tenant, networks);
+
+ if (router != null) {
+ associateRouterToVpn(vpn, router);
+ }
+ if (networks != null) {
+ associateNetworksToVpn(vpn, networks);
+ }
+ }
+
+ @Override
+ public Future<RpcResult<CreateL3VPNOutput>> createL3VPN(CreateL3VPNInput input) {
+
+ CreateL3VPNOutputBuilder opBuilder = new CreateL3VPNOutputBuilder();
+ SettableFuture<RpcResult<CreateL3VPNOutput>> result = SettableFuture.create();
+ List<RpcError> errorList = new ArrayList<RpcError>();
+ int failurecount = 0;
+ int warningcount = 0;
+
+ List<L3vpn> vpns = input.getL3vpn();
+ for (L3vpn vpn : vpns) {
+ RpcError error = null;
+ String msg;
+ if (vpn.getRouteDistinguisher() == null || vpn.getImportRT() == null || vpn.getExportRT() == null) {
+ msg = String.format("Creation of L3VPN failed for VPN %s due to absence of RD/iRT/eRT input",
+ vpn.getId().getValue());
+ logger.warn(msg);
+ error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
+ errorList.add(error);
+ warningcount++;
+ continue;
+ }
+ if (vpn.getRouteDistinguisher().size() > 1) {
+ msg = String.format("Creation of L3VPN failed for VPN %s due to multiple RD input %s",
+ vpn.getId().getValue(), vpn.getRouteDistinguisher());
+ logger.warn(msg);
+ error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
+ errorList.add(error);
+ warningcount++;
+ continue;
+ }
+ if (vpn.getRouterId() != null) {
+ if (NeutronvpnUtils.getNeutronRouter(broker, vpn.getRouterId()) == null) {
+ msg = String.format("Creation of L3VPN failed for VPN %s due to router not found %s",
+ vpn.getId().getValue(), vpn.getRouterId().getValue());
+ logger.warn(msg);
+ error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
+ errorList.add(error);
+ warningcount++;
+ continue;
+ }
+ Uuid vpnId = NeutronvpnUtils.getVpnForRouter(broker, vpn.getRouterId(), true);
+ if (vpnId != null) {
+ msg = String.format("Creation of L3VPN failed for VPN %s due to router %s already associated to " +
+ "another VPN %s", vpn.getId().getValue(), vpn.getRouterId().getValue(), vpnId.getValue());
+ logger.warn(msg);
+ error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
+ errorList.add(error);
+ warningcount++;
+ continue;
+ }
+ }
+ if (vpn.getNetworkIds() != null) {
+ for (Uuid nw : vpn.getNetworkIds()) {
+ Network network = NeutronvpnUtils.getNeutronNetwork(broker, nw);
+ Uuid vpnId = NeutronvpnUtils.getVpnForNetwork(broker, nw);
+ if (network == null) {
+ msg = String.format("Creation of L3VPN failed for VPN %s due to network not found %s",
+ vpn.getId().getValue(), nw.getValue());
+ logger.warn(msg);
+ error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
+ errorList.add(error);
+ warningcount++;
+ } else if (vpnId != null) {
+ msg = String.format("Creation of L3VPN failed for VPN %s due to network %s already associated" +
+ " to another VPN %s", vpn.getId().getValue(), nw.getValue(), vpnId.getValue());
+ logger.warn(msg);
+ error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-input", msg);
+ errorList.add(error);
+ warningcount++;
+ }
+ }
+ if (error != null) {
+ continue;
+ }
+ }
+ try {
+ createL3Vpn(vpn.getId(), vpn.getName(), vpn.getTenantId(), vpn.getRouteDistinguisher(),
+ vpn.getImportRT(), vpn.getExportRT(), vpn.getRouterId(), vpn.getNetworkIds());
+ } catch (Exception ex) {
+ msg = String.format("Creation of L3VPN failed for VPN %s", vpn.getId().getValue());
+ logger.error(msg, ex);
+ error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
+ errorList.add(error);
+ failurecount++;
+ }
+ }
+ // if at least one succeeds; result is success
+ // if none succeeds; result is failure
+ if (failurecount + warningcount == vpns.size()) {
+ result.set(RpcResultBuilder.<CreateL3VPNOutput>failed().withRpcErrors(errorList).build());
+ } else {
+ List<String> errorResponseList = new ArrayList<>();
+ if (!errorList.isEmpty()) {
+ for (RpcError rpcError : errorList) {
+ String errorResponse = String.format("ErrorType: " + rpcError.getErrorType() + ", " + "ErrorTag: " +
+ rpcError.getTag() + ", " + "ErrorMessage: " + rpcError.getMessage());
+ errorResponseList.add(errorResponse);
+ }
+ } else {
+ errorResponseList.add("Operation successful with no errors");
+ }
+ opBuilder.setResponse(errorResponseList);
+ result.set(RpcResultBuilder.<CreateL3VPNOutput>success().withResult(opBuilder.build()).build());
+ }
+ return result;
+ }
+
+ @Override
+ public Future<RpcResult<GetL3VPNOutput>> getL3VPN(GetL3VPNInput input) {
+
+ GetL3VPNOutputBuilder opBuilder = new GetL3VPNOutputBuilder();
+ SettableFuture<RpcResult<GetL3VPNOutput>> result = SettableFuture.create();
+ Uuid inputVpnId = input.getId();
+ List<VpnInstance> vpns = new ArrayList<VpnInstance>();
+
+ try {
+ if (inputVpnId == null) {
+ // get all vpns
+ InstanceIdentifier<VpnInstances> vpnsIdentifier =
+ InstanceIdentifier.builder(VpnInstances.class).build();
+ Optional<VpnInstances> optionalVpns = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
+ vpnsIdentifier);
+ if (optionalVpns.isPresent() && optionalVpns.get().getVpnInstance() != null) {
+ for (VpnInstance vpn : optionalVpns.get().getVpnInstance()) {
+ // eliminating internal VPNs from getL3VPN output
+ if (vpn.getIpv4Family().getRouteDistinguisher() != null) {
+ vpns.add(vpn);
+ }
+ }
+ } else {
+ // No VPN present
+ result.set(RpcResultBuilder.<GetL3VPNOutput>failed()
+ .withWarning(ErrorType.PROTOCOL, "", "No VPN is present").build());
+ return result;
+ }
+ } else {
+ String name = inputVpnId.getValue();
+ InstanceIdentifier<VpnInstance> vpnIdentifier =
+ InstanceIdentifier.builder(VpnInstances.class)
+ .child(VpnInstance.class, new VpnInstanceKey(name)).build();
+ // read VpnInstance Info
+ Optional<VpnInstance> optionalVpn = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
+ vpnIdentifier);
+ if (optionalVpn.isPresent()) {
+ vpns.add(optionalVpn.get());
+ } else {
+ String message = String.format("GetL3VPN failed because VPN %s is not present", name);
+ logger.error(message);
+ result.set(RpcResultBuilder.<GetL3VPNOutput>failed()
+ .withWarning(ErrorType.PROTOCOL, "invalid-value", message).build());
+ }
+ }
+ List<L3vpnInstances> l3vpnList = new ArrayList<L3vpnInstances>();
+ for (VpnInstance vpnInstance : vpns) {
+ Uuid vpnId = new Uuid(vpnInstance.getVpnInstanceName());
+ // create VpnMaps id
+ InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap
+ .class, new VpnMapKey(vpnId)).build();
+ L3vpnInstancesBuilder l3vpn = new L3vpnInstancesBuilder();
+
+ List<String> rd = Arrays.asList(vpnInstance.getIpv4Family().getRouteDistinguisher().split(","));
+ List<VpnTarget> vpnTargetList = vpnInstance.getIpv4Family().getVpnTargets().getVpnTarget();
+
+ List<String> ertList = new ArrayList<String>();
+ List<String> irtList = new ArrayList<String>();
+
+ for (VpnTarget vpnTarget : vpnTargetList) {
+ if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
+ ertList.add(vpnTarget.getVrfRTValue());
+ }
+ if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
+ irtList.add(vpnTarget.getVrfRTValue());
+ }
+ if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
+ ertList.add(vpnTarget.getVrfRTValue());
+ irtList.add(vpnTarget.getVrfRTValue());
+ }
+ }
+
+ l3vpn.setId(vpnId).setRouteDistinguisher(rd).setImportRT(irtList).setExportRT(ertList);
+ Optional<VpnMap> optionalVpnMap = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
+ vpnMapIdentifier);
+ if (optionalVpnMap.isPresent()) {
+ VpnMap vpnMap = optionalVpnMap.get();
+ l3vpn.setRouterId(vpnMap.getRouterId()).setNetworkIds(vpnMap.getNetworkIds())
+ .setTenantId(vpnMap.getTenantId()).setName(vpnMap.getName());
+ }
+ l3vpnList.add(l3vpn.build());
+ }
+
+ opBuilder.setL3vpnInstances(l3vpnList);
+ result.set(RpcResultBuilder.<GetL3VPNOutput>success().withResult(opBuilder.build()).build());
+
+ } catch (Exception ex) {
+ String message = String.format("GetL3VPN failed due to %s", ex.getMessage());
+ logger.error(message, ex);
+ result.set(RpcResultBuilder.<GetL3VPNOutput>failed().withError(ErrorType.APPLICATION, message).build());
+ }
+ return result;
+ }
+
+ @Override
+ public Future<RpcResult<DeleteL3VPNOutput>> deleteL3VPN(DeleteL3VPNInput input) {
+
+ DeleteL3VPNOutputBuilder opBuilder = new DeleteL3VPNOutputBuilder();
+ SettableFuture<RpcResult<DeleteL3VPNOutput>> result = SettableFuture.create();
+ List<RpcError> errorList = new ArrayList<RpcError>();
+
+ int failurecount = 0;
+ int warningcount = 0;
+ List<Uuid> vpns = input.getId();
+ for (Uuid vpn : vpns) {
+ RpcError error;
+ String msg;
+ try {
+ InstanceIdentifier<VpnInstance> vpnIdentifier =
+ InstanceIdentifier.builder(VpnInstances.class)
+ .child(VpnInstance.class, new VpnInstanceKey(vpn.getValue())).build();
+ Optional<VpnInstance> optionalVpn = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
+ vpnIdentifier);
+ if (optionalVpn.isPresent()) {
+ removeL3Vpn(vpn);
+ } else {
+ msg = String.format("VPN with vpnid: %s does not exist", vpn.getValue());
+ logger.warn(msg);
+ error = RpcResultBuilder.newWarning(ErrorType.PROTOCOL, "invalid-value", msg);
+ errorList.add(error);
+ warningcount++;
+ }
+ } catch (Exception ex) {
+ msg = String.format("Deletion of L3VPN failed when deleting for uuid %s", vpn.getValue());
+ logger.error(msg, ex);
+ error = RpcResultBuilder.newError(ErrorType.APPLICATION, msg, ex.getMessage());
+ errorList.add(error);
+ failurecount++;
+ }
+ }
+ // if at least one succeeds; result is success
+ // if none succeeds; result is failure
+ if (failurecount + warningcount == vpns.size()) {
+ result.set(RpcResultBuilder.<DeleteL3VPNOutput>failed().withRpcErrors(errorList).build());
+ } else {
+ List<String> errorResponseList = new ArrayList<>();
+ if (!errorList.isEmpty()) {
+ for (RpcError rpcError : errorList) {
+ String errorResponse = String.format("ErrorType: " + rpcError.getErrorType() + ", " + "ErrorTag: " +
+ rpcError.getTag() + ", " + "ErrorMessage: " + rpcError.getMessage());
+ errorResponseList.add(errorResponse);
+ }
+ } else {
+ errorResponseList.add("Operation successful with no errors");
+ }
+ opBuilder.setResponse(errorResponseList);
+ result.set(RpcResultBuilder.<DeleteL3VPNOutput>success().withResult(opBuilder.build()).build());
+ }
+ return result;
+ }
+
+ protected void addSubnetToVpn(Uuid vpnId, Uuid subnet) {
+ logger.debug("Adding subnet {} to vpn {}", subnet.getValue(), vpnId.getValue());
+ Subnetmap sn = updateSubnetNode(subnet, null, null, null, null, vpnId, null);
+ boolean isLockAcquired = false;
+ String lockName = vpnId.getValue() + subnet.getValue();
+ String elanInstanceName = sn.getNetworkId().getValue();
+ InstanceIdentifier<ElanInstance>elanIdentifierId = InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
+ Optional<ElanInstance> elanInstance = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION, elanIdentifierId);
+ long elanTag = elanInstance.get().getElanTag();
+ Uuid routerId = NeutronvpnUtils.getVpnMap(broker, vpnId).getRouterId();
+ if (vpnId.equals(routerId)) {
+ isExternalVpn = false;
+ } else {
+ isExternalVpn = true;
+ }
+ try {
+ isLockAcquired = NeutronvpnUtils.lock(lockManager, lockName);
+ checkAndPublishSubnetAddNotification(subnet, sn.getSubnetIp(), vpnId.getValue(), isExternalVpn, elanTag);
+ logger.debug("Subnet added to Vpn notification sent");
+ }catch (Exception e){
+ logger.error("Subnet added to Vpn notification failed",e);
+ }finally {
+ if (isLockAcquired) {
+ NeutronvpnUtils.unlock(lockManager, lockName);
+ }
+ }
+ // Check if there are ports on this subnet and add corresponding vpn-interfaces
+ List<Uuid> portList = sn.getPortList();
+ if (portList != null) {
+ for (Uuid port : sn.getPortList()) {
+ logger.debug("adding vpn-interface for port {}", port.getValue());
+ createVpnInterface(vpnId, NeutronvpnUtils.getNeutronPort(broker, port));
+ }
+ }
+ }
+
+ protected void updateVpnForSubnet(Uuid vpnId, Uuid subnet, boolean isBeingAssociated) {
+ logger.debug("Updating VPN {} for subnet {}", vpnId.getValue(), subnet.getValue());
+ Subnetmap sn = updateSubnetNode(subnet, null, null, null, null, vpnId, null);
+ boolean isLockAcquired = false;
+ String lockName = vpnId.getValue() + subnet.getValue();
+ String elanInstanceName = sn.getNetworkId().getValue();
+ InstanceIdentifier<ElanInstance>elanIdentifierId = InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
+ Optional<ElanInstance> elanInstance = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION, elanIdentifierId);
+ long elanTag = elanInstance.get().getElanTag();
+ try {
+ isLockAcquired = NeutronvpnUtils.lock(lockManager, lockName);
+ checkAndPublishSubnetUpdNotification(subnet, sn.getSubnetIp(), vpnId.getValue(), isBeingAssociated, elanTag);
+ logger.debug("Subnet updated in Vpn notification sent");
+ }catch (Exception e){
+ logger.error("Subnet updated in Vpn notification failed",e);
+ }finally {
+ if (isLockAcquired) {
+ NeutronvpnUtils.unlock(lockManager, lockName);
+ }
+ }
+ // Check for ports on this subnet and update association of corresponding vpn-interfaces to external vpn
+ List<Uuid> portList = sn.getPortList();
+ if (portList != null) {
+ for (Uuid port : sn.getPortList()) {
+ logger.debug("Updating vpn-interface for port {}", port.getValue());
+ updateVpnInterface(vpnId, NeutronvpnUtils.getNeutronPort(broker, port));
+ }
+ }
+ }
+
+
+
+ // router-interfaces-map
+// list router-interfaces {
+// key router-id;
+// leaf router-id { type yang:uuid; }
+// list interfaces {
+// key interface-id;
+// leaf interface-id { type yang:uuid; }
+// }
+// }
+////}
+ InstanceIdentifier<RouterInterfaces> getRouterInterfacesId(Uuid routerId) {
+ return InstanceIdentifier.builder(RouterInterfacesMap.class)
+ .child(RouterInterfaces.class, new RouterInterfacesKey(routerId)).build();
+ }
+ void addToNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
+ InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
+ Optional<RouterInterfaces> optRouterInterfaces = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId);
+ Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName)).setInterfaceId(interfaceName).build();
+ if(optRouterInterfaces.isPresent()) {
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)), routerInterface);
+ } else {
+ RouterInterfacesBuilder builder = new RouterInterfacesBuilder().setRouterId(routerId);
+ List<Interfaces> interfaces = new ArrayList<>();
+ interfaces.add(routerInterface);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId, builder.setInterfaces(interfaces).build());
+ }
+ }
+
+ void removeFromNeutronRouterInterfacesMap(Uuid routerId, String interfaceName) {
+ InstanceIdentifier<RouterInterfaces> routerInterfacesId = getRouterInterfacesId(routerId);
+ Optional<RouterInterfaces> optRouterInterfaces = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId);
+ Interfaces routerInterface = new InterfacesBuilder().setKey(new InterfacesKey(interfaceName)).setInterfaceId(interfaceName).build();
+ if(optRouterInterfaces.isPresent()) {
+ RouterInterfaces routerInterfaces = optRouterInterfaces.get();
+ List<Interfaces> interfaces = routerInterfaces.getInterfaces();
+ if(interfaces != null && interfaces.remove(routerInterface)) {
+ if(interfaces.isEmpty()) {
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId);
+ } else {
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, routerInterfacesId.child(Interfaces.class, new InterfacesKey(interfaceName)));
+ }
+ }
+ }
+ }
+
+ protected List<Adjacency> addAdjacencyforExtraRoute(List<Routes> routeList, boolean rtrUp, String vpnifname) {
+ List<Adjacency> adjList = new ArrayList<Adjacency>();
+ for (Routes route : routeList) {
+ if (route != null && route.getNexthop() != null && route.getDestination() != null) {
+ boolean isLockAcquired = false;
+ String nextHop = String.valueOf(route.getNexthop().getValue());
+ String destination = String.valueOf(route.getDestination().getValue());
+
+ String infName = NeutronvpnUtils.getNeutronPortNamefromPortFixedIp(broker, nextHop);
+ logger.trace("Adding extra route with nexthop {}, destination {}, infName {}", nextHop,
+ destination, infName);
+ Adjacency erAdj = new AdjacencyBuilder().setIpAddress(destination).setNextHopIp(nextHop).setKey
+ (new AdjacencyKey(destination)).build();
+ if (rtrUp == false) {
+ if (infName.equals(vpnifname)) {
+ adjList.add(erAdj);
+ }
+ continue;
+ }
+ InstanceIdentifier<VpnInterface> vpnIfIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
+ child(VpnInterface.class, new VpnInterfaceKey(infName)).build();
+ try {
+ Optional<VpnInterface> optionalVpnInterface = NeutronvpnUtils.read(broker, LogicalDatastoreType
+ .CONFIGURATION, vpnIfIdentifier);
+ if (optionalVpnInterface.isPresent()) {
+ Adjacencies erAdjs = new AdjacenciesBuilder().setAdjacency(Arrays.asList(erAdj)).build();
+ VpnInterface vpnIf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(infName))
+ .addAugmentation(Adjacencies.class, erAdjs).build();
+ isLockAcquired = NeutronvpnUtils.lock(lockManager, infName);
+ logger.debug("Adding extra route {}", route);
+ MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, vpnIf);
+ } else {
+ logger.error("VM adjacency for interface {} not present ; cannot add extra route adjacency",
+ infName);
+ }
+ } catch (Exception e) {
+ logger.error("exception in adding extra route: {}" + e);
+ } finally {
+ if (isLockAcquired) {
+ NeutronvpnUtils.unlock(lockManager, infName);
+ }
+ }
+ } else {
+ logger.error("Incorrect input received for extra route. {}", route);
+ }
+ }
+ return adjList;
+ }
+
+ protected void removeAdjacencyforExtraRoute(List<Routes> routeList) {
+ for (Routes route : routeList) {
+ if (route != null && route.getNexthop() != null && route.getDestination() != null) {
+ boolean isLockAcquired = false;
+ String nextHop = String.valueOf(route.getNexthop().getValue());
+ String destination = String.valueOf(route.getDestination().getValue());
+
+ String infName = NeutronvpnUtils.getNeutronPortNamefromPortFixedIp(broker, nextHop);
+ logger.trace("Removing extra route with nexthop {}, destination {}, infName {}", nextHop,
+ destination, infName);
+ InstanceIdentifier<Adjacency> adjacencyIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
+ child(VpnInterface.class, new VpnInterfaceKey(infName)).augmentation(Adjacencies.class)
+ .child(Adjacency.class, new AdjacencyKey(destination)).build();
+ try {
+ isLockAcquired = NeutronvpnUtils.lock(lockManager, infName);
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
+ logger.trace("extra route {} deleted successfully", route);
+ } catch (Exception e) {
+ logger.error("exception in deleting extra route: {}" + e);
+ } finally {
+ if (isLockAcquired) {
+ NeutronvpnUtils.unlock(lockManager, infName);
+ }
+ }
+ } else {
+ logger.error("Incorrect input received for extra route. {}", route);
+ }
+ }
+ }
+
+ protected void removeL3Vpn(Uuid id) {
+ // read VPNMaps
+ VpnMap vpnMap = NeutronvpnUtils.getVpnMap(broker, id);
+ Uuid router = vpnMap.getRouterId();
+ // dissociate router
+ if (router != null) {
+ dissociateRouterFromVpn(id, router);
+ }
+ // dissociate networks
+ if (!id.equals(router)) {
+ dissociateNetworksFromVpn(id, vpnMap.getNetworkIds());
+ }
+ // remove entire vpnMaps node
+ deleteVpnMapsNode(id);
+
+ // remove vpn-instance
+ deleteVpnInstance(id);
+ }
+
+ protected void removeSubnetFromVpn(Uuid vpnId, Uuid subnet) {
+ logger.debug("Removing subnet {} from vpn {}", subnet.getValue(), vpnId.getValue());
+ Subnetmap sn = NeutronvpnUtils.getSubnetmap(broker, subnet);
+ boolean isLockAcquired = false;
+ String lockName = vpnId.getValue() + subnet.getValue();
+ String elanInstanceName = sn.getNetworkId().getValue();
+ InstanceIdentifier<ElanInstance>elanIdentifierId = InstanceIdentifier.builder(ElanInstances.class).child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
+ Optional<ElanInstance> elanInstance = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION, elanIdentifierId);
+ long elanTag = elanInstance.get().getElanTag();
+ Uuid routerId = NeutronvpnUtils.getVpnMap(broker, vpnId).getRouterId();
+ if (vpnId.equals(routerId)) {
+ isExternalVpn = false;
+ } else {
+ isExternalVpn = true;
+ }
+ try {
+ isLockAcquired = NeutronvpnUtils.lock(lockManager, lockName);
+ checkAndPublishSubnetDelNotification(subnet, sn.getSubnetIp(), vpnId.getValue(), isExternalVpn, elanTag);
+ logger.debug("Subnet removed from Vpn notification sent");
+ }catch (Exception e){
+ logger.error("Subnet removed from Vpn notification failed",e);
+ }finally {
+ if (isLockAcquired) {
+ NeutronvpnUtils.unlock(lockManager, lockName);
+ }
+ }
+ if (sn != null) {
+ // Check if there are ports on this subnet; remove corresponding vpn-interfaces
+ List<Uuid> portList = sn.getPortList();
+ if (portList != null) {
+ for (Uuid port : sn.getPortList()) {
+ logger.debug("removing vpn-interface for port {}", port.getValue());
+ deleteVpnInterface(NeutronvpnUtils.getNeutronPort(broker, port));
+ if (routerId != null) {
+ removeFromNeutronRouterInterfacesMap(routerId, port.getValue());
+ }
+ }
+ }
+ // update subnet-vpn association
+ removeFromSubnetNode(subnet, null, null, vpnId, null);
+ } else {
+ logger.warn("Subnetmap for subnet {} not found", subnet.getValue());
+ }
+ }
+
+ protected void associateRouterToVpn(Uuid vpnId, Uuid routerId) {
+ updateVpnMaps(vpnId, null, routerId, null, null);
+ List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(broker, routerId);
+ if (!vpnId.equals(routerId)) {
+ logger.debug("Updating association of subnets to external vpn {}", vpnId.getValue());
+ if (routerSubnets != null) {
+ for (Uuid subnetId : routerSubnets) {
+ updateVpnForSubnet(vpnId, subnetId,true);
+ }
+ }
+ } else {
+ logger.debug("Adding subnets to internal vpn {}", vpnId.getValue());
+ for (Uuid subnet : routerSubnets) {
+ addSubnetToVpn(vpnId, subnet);
+ }
+ }
+ }
+
+ protected void dissociateRouterFromVpn(Uuid vpnId, Uuid routerId) {
+
+ List<Uuid> routerSubnets = NeutronvpnUtils.getNeutronRouterSubnetIds(broker, routerId);
+ if (routerSubnets != null) {
+ for (Uuid subnetId : routerSubnets) {
+ logger.debug("Updating association of subnets to internal vpn {}", routerId.getValue());
+ updateVpnForSubnet(routerId, subnetId,false);
+ }
+ }
+ clearFromVpnMaps(vpnId, routerId, null);
+ }
+
+ protected List<String> associateNetworksToVpn(Uuid vpn, List<Uuid> networks) {
+ List<String> failed = new ArrayList<String>();
+ if (!networks.isEmpty()) {
+ // store in Data Base
+ updateVpnMaps(vpn, null, null, null, networks);
+ // process corresponding subnets for VPN
+ for (Uuid nw : networks) {
+ if (NeutronvpnUtils.getNeutronNetwork(broker, nw) == null) {
+ failed.add(nw.getValue());
+ } else {
+ List<Uuid> networkSubnets = NeutronvpnUtils.getSubnetIdsFromNetworkId(broker, nw);
+ logger.debug("Adding network subnets...");
+ if (networkSubnets != null) {
+ for (Uuid subnet : networkSubnets) {
+ addSubnetToVpn(vpn, subnet);
+ }
+ }
+ }
+ }
+ }
+ return failed;
+ }
+
+ protected List<String> dissociateNetworksFromVpn(Uuid vpn, List<Uuid> networks) {
+ List<String> failed = new ArrayList<String>();
+ if (networks != null && !networks.isEmpty()) {
+ // store in Data Base
+ clearFromVpnMaps(vpn, null, networks);
+ // process corresponding subnets for VPN
+ for (Uuid nw : networks) {
+ if (NeutronvpnUtils.getNeutronNetwork(broker, nw) == null) {
+ failed.add(nw.getValue());
+ } else {
+ List<Uuid> networkSubnets = NeutronvpnUtils.getSubnetIdsFromNetworkId(broker, nw);
+ logger.debug("Removing network subnets...");
+ if (networkSubnets != null) {
+ for (Uuid subnet : networkSubnets) {
+ removeSubnetFromVpn(vpn, subnet);
+ }
+ }
+ }
+ }
+ }
+ return failed;
+ }
+
+ @Override
+ public Future<RpcResult<AssociateNetworksOutput>> associateNetworks(AssociateNetworksInput input) {
+
+ AssociateNetworksOutputBuilder opBuilder = new AssociateNetworksOutputBuilder();
+ SettableFuture<RpcResult<AssociateNetworksOutput>> result = SettableFuture.create();
+ logger.debug("associateNetworks {}", input);
+ StringBuilder returnMsg = new StringBuilder();
+ Uuid vpnId = input.getVpnId();
+
+ try {
+ if (NeutronvpnUtils.getVpnMap(broker, vpnId) != null) {
+ List<Uuid> netIds = input.getNetworkId();
+ if (netIds != null && !netIds.isEmpty()) {
+ List<String> failed = associateNetworksToVpn(vpnId, netIds);
+ if (!failed.isEmpty()) {
+ returnMsg.append("network(s) not found : ").append(failed);
+ }
+ }
+ } else {
+ returnMsg.append("VPN not found : ").append(vpnId.getValue());
+ }
+ if (returnMsg.length() != 0) {
+ String message = String.format("associate Networks to vpn %s failed due to %s", vpnId.getValue(),
+ returnMsg);
+ logger.error(message);
+ String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " +
+ message);
+ opBuilder.setResponse(errorResponse);
+ result.set(RpcResultBuilder.<AssociateNetworksOutput>success().withResult(opBuilder.build()).build());
+ } else {
+ result.set(RpcResultBuilder.<AssociateNetworksOutput>success().build());
+ }
+ } catch (Exception ex) {
+ String message = String.format("associate Networks to vpn %s failed due to %s", input.getVpnId().getValue(),
+ ex.getMessage());
+ logger.error(message, ex);
+ result.set(RpcResultBuilder.<AssociateNetworksOutput>failed().withError(ErrorType.APPLICATION, message)
+ .build());
+ }
+ logger.debug("associateNetworks returns..");
+ return result;
+ }
+
+ @Override
+ public Future<RpcResult<Void>> associateRouter(AssociateRouterInput input) {
+
+ SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+ logger.debug("associateRouter {}", input);
+ StringBuilder returnMsg = new StringBuilder();
+ Uuid vpnId = input.getVpnId();
+ Uuid routerId = input.getRouterId();
+ try {
+ if (routerId != null && vpnId != null) {
+ Router rtr = NeutronvpnUtils.getNeutronRouter(broker, routerId);
+ VpnMap vpnMap = NeutronvpnUtils.getVpnMap(broker, vpnId);
+ if (rtr != null && vpnMap != null) {
+ if (vpnMap.getRouterId() != null) {
+ returnMsg.append("vpn ").append(vpnId.getValue()).append(" already associated to router ")
+ .append(vpnMap.getRouterId().getValue());
+ } else {
+ associateRouterToVpn(vpnId, routerId);
+ }
+ } else {
+ returnMsg.append("router not found : ").append(routerId.getValue());
+ }
+ } else {
+ returnMsg.append("VPN not found : ").append(vpnId.getValue());
+ }
+ if (returnMsg.length() != 0) {
+ String message = String.format("associate router to vpn %s failed due to %s", routerId.getValue(),
+ returnMsg);
+ logger.error(message);
+ result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
+ .build());
+ } else {
+ result.set(RpcResultBuilder.<Void>success().build());
+ }
+ } catch (Exception ex) {
+ String message = String.format("associate router %s to vpn %s failed due to %s", routerId.getValue(),
+ vpnId.getValue(), ex.getMessage());
+ logger.error(message, ex);
+ result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, message).build());
+ }
+ logger.debug("associateRouter returns..");
+ return result;
+ }
+
+ @Override
+ public Future<RpcResult<DissociateNetworksOutput>> dissociateNetworks(DissociateNetworksInput input) {
+
+ DissociateNetworksOutputBuilder opBuilder = new DissociateNetworksOutputBuilder();
+ SettableFuture<RpcResult<DissociateNetworksOutput>> result = SettableFuture.create();
+
+ logger.debug("dissociateNetworks {}", input);
+ StringBuilder returnMsg = new StringBuilder();
+ Uuid vpnId = input.getVpnId();
+
+ try {
+ if (NeutronvpnUtils.getVpnMap(broker, vpnId) != null) {
+ List<Uuid> netIds = input.getNetworkId();
+ if (netIds != null && !netIds.isEmpty()) {
+ List<String> failed = dissociateNetworksFromVpn(vpnId, netIds);
+ if (!failed.isEmpty()) {
+ returnMsg.append("netowrk(s) not found : ").append(failed);
+ }
+ }
+ } else {
+ returnMsg.append("VPN not found : ").append(vpnId.getValue());
+ }
+ if (returnMsg.length() != 0) {
+ String message = String.format("dissociate Networks to vpn %s failed due to %s", vpnId.getValue(),
+ returnMsg);
+ logger.error(message);
+ String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " +
+ message);
+ opBuilder.setResponse(errorResponse);
+ result.set(RpcResultBuilder.<DissociateNetworksOutput>success().withResult(opBuilder.build()).build());
+ } else {
+ result.set(RpcResultBuilder.<DissociateNetworksOutput>success().build());
+ }
+ } catch (Exception ex) {
+ String message = String.format("dissociate Networks to vpn %s failed due to %s", input.getVpnId().
+ getValue(), ex.getMessage());
+ logger.error(message, ex);
+ result.set(RpcResultBuilder.<DissociateNetworksOutput>failed().withError(ErrorType.APPLICATION, message)
+ .build());
+ }
+ logger.debug("dissociateNetworks returns..");
+ return result;
+ }
+
+ @Override
+ public Future<RpcResult<Void>> dissociateRouter(DissociateRouterInput input) {
+
+ SettableFuture<RpcResult<Void>> result = SettableFuture.create();
+
+ logger.debug("dissociateRouter {}", input);
+ StringBuilder returnMsg = new StringBuilder();
+ Uuid vpnId = input.getVpnId();
+ Uuid routerId = input.getRouterId();
+ try {
+ if (NeutronvpnUtils.getVpnMap(broker, vpnId) != null) {
+ if (routerId != null) {
+ Router rtr = NeutronvpnUtils.getNeutronRouter(broker, routerId);
+ if (rtr != null) {
+ dissociateRouterFromVpn(vpnId, routerId);
+ } else {
+ returnMsg.append("router not found : ").append(routerId.getValue());
+ }
+ }
+ } else {
+ returnMsg.append("VPN not found : ").append(vpnId.getValue());
+ }
+ if (returnMsg.length() != 0) {
+ String message = String.format("dissociate router %s to vpn %s failed due to %s", routerId.getValue(),
+ vpnId.getValue(), returnMsg);
+ logger.error(message);
+ String errorResponse = String.format("ErrorType: PROTOCOL, ErrorTag: invalid-value, ErrorMessage: " +
+ message);
+ result.set(RpcResultBuilder.<Void>failed().withWarning(ErrorType.PROTOCOL, "invalid-value", message)
+ .build());
+ } else {
+ result.set(RpcResultBuilder.<Void>success().build());
+ }
+ } catch (Exception ex) {
+ String message = String.format("disssociate router %s to vpn %s failed due to %s", routerId.getValue(),
+ vpnId.getValue(), ex.getMessage());
+ logger.error(message, ex);
+ result.set(RpcResultBuilder.<Void>failed().withError(ErrorType.APPLICATION, message).build());
+ }
+ logger.debug("dissociateRouter returns..");
+
+ return result;
+ }
+
+ @Override
+ public Future<RpcResult<GetFixedIPsForNeutronPortOutput>> getFixedIPsForNeutronPort(GetFixedIPsForNeutronPortInput
+ input) {
+ GetFixedIPsForNeutronPortOutputBuilder opBuilder = new GetFixedIPsForNeutronPortOutputBuilder();
+ SettableFuture<RpcResult<GetFixedIPsForNeutronPortOutput>> result = SettableFuture.create();
+ Uuid portId = input.getPortId();
+ StringBuilder returnMsg = new StringBuilder();
+ try {
+ List<String> fixedIPList = new ArrayList<>();
+ Port port = NeutronvpnUtils.getNeutronPort(broker, portId);
+ if (port != null) {
+ List<FixedIps> fixedIPs = port.getFixedIps();
+ for (FixedIps ip : fixedIPs) {
+ fixedIPList.add(ip.getIpAddress().getIpv4Address().getValue());
+ }
+ } else {
+ returnMsg.append("neutron port: ").append(portId.getValue()).append(" not found");
+ }
+ if (returnMsg.length() != 0) {
+ String message = String.format("Retrieval of FixedIPList for neutron port failed due to %s", returnMsg);
+ logger.error(message);
+ result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withWarning(ErrorType.PROTOCOL,
+ "invalid-value", message).build());
+ } else {
+ opBuilder.setFixedIPs(fixedIPList);
+ result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().withResult(opBuilder.build())
+ .build());
+ result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>success().build());
+ }
+ } catch (Exception ex) {
+ String message = String.format("Retrieval of FixedIPList for neutron port %s failed due to %s", portId
+ .getValue(), ex.getMessage());
+ logger.error(message, ex);
+ result.set(RpcResultBuilder.<GetFixedIPsForNeutronPortOutput>failed().withError(ErrorType.APPLICATION,
+ message).build());
+ }
+ return result;
+ }
+
+ protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
+ // check if the router is associated to some VPN
+ Uuid vpnId = NeutronvpnUtils.getVpnForRouter(broker, routerId, true);
+ if (vpnId != null) {
+ // remove existing external vpn interfaces
+ for (Uuid subnetId : routerSubnetIds) {
+ removeSubnetFromVpn(vpnId, subnetId);
+ }
+ clearFromVpnMaps(vpnId, routerId, null);
+ } else {
+ // remove existing internal vpn interfaces
+ for (Uuid subnetId : routerSubnetIds) {
+ removeSubnetFromVpn(routerId, subnetId);
+ }
+ }
+ // delete entire vpnMaps node for internal VPN
+ deleteVpnMapsNode(routerId);
+
+ // delete vpn-instance for internal VPN
+ deleteVpnInstance(routerId);
+ }
+
+ protected Subnet getNeutronSubnet(Uuid subnetId) {
+ InstanceIdentifier<Subnet> inst = InstanceIdentifier.create(Neutron.class).
+ child(Subnets.class).child(Subnet.class, new SubnetKey(subnetId));
+ Optional<Subnet> sn = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION, inst);
+
+ if (sn.isPresent()) {
+ return sn.get();
+ }
+ return null;
+ }
+
+ protected IpAddress getNeutronSubnetGateway(Uuid subnetId) {
+ Subnet sn = getNeutronSubnet(subnetId);
+ if (null != sn) {
+ return sn.getGatewayIp();
+ }
+ return null;
+ }
+
+ protected Port getNeutronPort(String name) {
+ return NeutronvpnUtils.getNeutronPort(broker, new Uuid(name));
+ }
+
+ protected Port getNeutronPort(Uuid portId) {
+ return NeutronvpnUtils.getNeutronPort(broker, portId);
+ }
+
+ protected List<Uuid> getSubnetsforVpn(Uuid vpnid) {
+ List<Uuid> subnets = new ArrayList<Uuid>();
+ //read subnetmaps
+ InstanceIdentifier<Subnetmaps> subnetmapsid = InstanceIdentifier.builder(Subnetmaps.class).build();
+ Optional<Subnetmaps> subnetmaps = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
+ subnetmapsid);
+ if (subnetmaps.isPresent() && subnetmaps.get().getSubnetmap() != null) {
+ List<Subnetmap> subnetMapList = subnetmaps.get().getSubnetmap();
+ for (Subnetmap subnetMap : subnetMapList) {
+ if (subnetMap.getVpnId() != null && subnetMap.getVpnId().equals(vpnid)) {
+ subnets.add(subnetMap.getId());
+ }
+ }
+ }
+ return subnets;
+ }
+
+ public List<String> showNeutronPortsCLI() {
+ List<String> result = new ArrayList<String>();
+ result.add(String.format(" %-34s %-22s %-22s %-6s ", "PortName", "Mac Address", "IP Address",
+ "Prefix Length"));
+ result.add("---------------------------------------------------------------------------------------");
+ InstanceIdentifier<Ports> portidentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class);
+ try {
+ Optional<Ports> ports = NeutronvpnUtils.read(broker, LogicalDatastoreType.CONFIGURATION, portidentifier);
+ if (ports.isPresent() && ports.get().getPort() != null) {
+ List<Port> portList = ports.get().getPort();
+ for (Port port : portList) {
+ result.add(String.format(" %-34s %-22s %-22s %-6s ", port.getUuid().getValue(), port
+ .getMacAddress(), port.getFixedIps().get(0).getIpAddress().getIpv4Address().getValue(),
+ NeutronvpnUtils.getIPPrefixFromPort(broker, port)));
+ }
+ }
+ } catch (Exception e) {
+ logger.error("Failed to retrieve neutronPorts info : ", e);
+ System.out.println("Failed to retrieve neutronPorts info : " + e.getMessage());
+ }
+ return result;
+ }
+
+ public List<String> showVpnConfigCLI(Uuid vpnuuid) {
+ List<String> result = new ArrayList<String>();
+ if (vpnuuid == null) {
+ System.out.println("");
+ System.out.println("Displaying VPN config for all VPNs");
+ System.out.println("To display VPN config for a particular VPN, use the following syntax");
+ System.out.println(getshowVpnConfigCLIHelp());
+ }
+ try {
+ RpcResult<GetL3VPNOutput> rpcResult = getL3VPN(new GetL3VPNInputBuilder().setId(vpnuuid).build()).get();
+ if (rpcResult.isSuccessful()) {
+ result.add("");
+ result.add(String.format(" %-37s %-37s %-7s ", "VPN ID", "Tenant ID", "RD"));
+ result.add("");
+ result.add(String.format(" %-80s ", "Import-RTs"));
+ result.add("");
+ result.add(String.format(" %-80s ", "Export-RTs"));
+ result.add("");
+ result.add(String.format(" %-76s ", "Subnet IDs"));
+ result.add("");
+ result.add("------------------------------------------------------------------------------------");
+ result.add("");
+ List<L3vpnInstances> VpnList = rpcResult.getResult().getL3vpnInstances();
+ for (L3vpnInstance Vpn : VpnList) {
+ String tenantId = Vpn.getTenantId() != null ? Vpn.getTenantId().getValue() : "\" " +
+ " \"";
+ result.add(String.format(" %-37s %-37s %-7s ", Vpn.getId().getValue(), tenantId, Vpn
+ .getRouteDistinguisher()));
+ result.add("");
+ result.add(String.format(" %-80s ", Vpn.getImportRT()));
+ result.add("");
+ result.add(String.format(" %-80s ", Vpn.getExportRT()));
+ result.add("");
+
+ Uuid vpnid = Vpn.getId();
+ List<Uuid> subnetList = getSubnetsforVpn(vpnid);
+ if (!subnetList.isEmpty()) {
+ for (Uuid subnetuuid : subnetList) {
+ result.add(String.format(" %-76s ", subnetuuid.getValue()));
+ }
+ } else {
+ result.add(String.format(" %-76s ", "\" \""));
+ }
+ result.add("");
+ result.add("----------------------------------------");
+ result.add("");
+ }
+ } else {
+ String errortag = rpcResult.getErrors().iterator().next().getTag();
+ if (errortag == "") {
+ System.out.println("");
+ System.out.println("No VPN has been configured yet");
+ } else if (errortag == "invalid-value") {
+ System.out.println("");
+ System.out.println("VPN " + vpnuuid.getValue() + " is not present");
+ } else {
+ System.out.println("error getting VPN info : " + rpcResult.getErrors());
+ System.out.println(getshowVpnConfigCLIHelp());
+ }
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ logger.error("error getting VPN info : ", e);
+ System.out.println("error getting VPN info : " + e.getMessage());
+ }
+ return result;
+ }
+
+ private String getshowVpnConfigCLIHelp() {
+ StringBuilder help = new StringBuilder("Usage:");
+ help.append("display vpn-config [-vid/--vpnid <id>]");
+ return help.toString();
+ }
+
+ private void checkAndPublishSubnetAddNotification(Uuid subnetId, String subnetIp, String vpnName, Boolean isExternalvpn, Long elanTag)throws InterruptedException{
+ SubnetAddedToVpnBuilder builder = new SubnetAddedToVpnBuilder();
+
+ logger.info("publish notification called");
+
+ builder.setSubnetId(subnetId);
+ builder.setSubnetIp(subnetIp);
+ builder.setVpnName(vpnName);
+ builder.setExternalVpn(isExternalvpn);
+ builder.setElanTag(elanTag);
+
+ notificationPublishService.putNotification(builder.build());
+ }
+
+ private void checkAndPublishSubnetDelNotification(Uuid subnetId, String subnetIp, String vpnName, Boolean isExternalvpn, Long elanTag)throws InterruptedException{
+ SubnetDeletedFromVpnBuilder builder = new SubnetDeletedFromVpnBuilder();
+
+ logger.info("publish notification called");
+
+ builder.setSubnetId(subnetId);
+ builder.setSubnetIp(subnetIp);
+ builder.setVpnName(vpnName);
+ builder.setExternalVpn(isExternalvpn);
+ builder.setElanTag(elanTag);
+
+ notificationPublishService.putNotification(builder.build());
+ }
+
+ private void checkAndPublishSubnetUpdNotification(Uuid subnetId, String subnetIp, String vpnName, Boolean isExternalvpn, Long elanTag)throws InterruptedException{
+ SubnetUpdatedInVpnBuilder builder = new SubnetUpdatedInVpnBuilder();
+
+ logger.info("publish notification called");
+
+ builder.setSubnetId(subnetId);
+ builder.setSubnetIp(subnetIp);
+ builder.setVpnName(vpnName);
+ builder.setExternalVpn(isExternalvpn);
+ builder.setElanTag(elanTag);
+
+ notificationPublishService.putNotification(builder.build());
+ }
+
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.neutronvpn;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.md.sal.binding.api.NotificationService;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+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.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.vpnservice.neutronvpn.interfaces.INeutronVpnManager;
+import org.opendaylight.vpnservice.neutronvpn.l2gw.L2GatewayProvider;
+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.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.NeutronvpnService;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+public class NeutronvpnProvider implements BindingAwareProvider, INeutronVpnManager, AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronvpnProvider.class);
+ private NeutronvpnManager nvManager;
+ private IMdsalApiManager mdsalManager;
+ private LockManagerService lockManager;
+ private NeutronBgpvpnChangeListener bgpvpnListener;
+ private NeutronNetworkChangeListener networkListener;
+ private NeutronSubnetChangeListener subnetListener;
+ private NeutronRouterChangeListener routerListener;
+ private NeutronPortChangeListener portListener;
+ private RpcProviderRegistry rpcProviderRegistry;
+ private L2GatewayProvider l2GatewayProvider;
+ private NotificationPublishService notificationPublishService;
+ private NotificationService notificationService;
+ private EntityOwnershipService entityOwnershipService;
+
+ public NeutronvpnProvider(RpcProviderRegistry rpcRegistry,NotificationPublishService notificationPublishService,
+ NotificationService notificationService) {
+ this.rpcProviderRegistry = rpcRegistry;
+ this.notificationPublishService = notificationPublishService;
+ this.notificationService = notificationService;
+ }
+
+ public RpcProviderRegistry getRpcProviderRegistry() {
+ return rpcProviderRegistry;
+ }
+
+ public void setRpcProviderRegistry(RpcProviderRegistry rpcProviderRegistry) {
+ this.rpcProviderRegistry = rpcProviderRegistry;
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ public void setLockManager(LockManagerService lockManager) {
+ this.lockManager = lockManager;
+ }
+
+ public void setEntityOwnershipService(EntityOwnershipService entityOwnershipService) {
+ this.entityOwnershipService = entityOwnershipService;
+ }
+
+ @Override
+ public void onSessionInitiated(ProviderContext session) {
+ try {
+ final DataBroker dbx = session.getSALService(DataBroker.class);
+ nvManager = new NeutronvpnManager(dbx, mdsalManager,notificationPublishService,notificationService);
+ final BindingAwareBroker.RpcRegistration<NeutronvpnService> rpcRegistration =
+ getRpcProviderRegistry().addRpcImplementation(NeutronvpnService.class, nvManager);
+ bgpvpnListener = new NeutronBgpvpnChangeListener(dbx, nvManager);
+ networkListener = new NeutronNetworkChangeListener(dbx, nvManager);
+ subnetListener = new NeutronSubnetChangeListener(dbx, nvManager);
+ routerListener = new NeutronRouterChangeListener(dbx, nvManager);
+ portListener = new NeutronPortChangeListener(dbx, nvManager,notificationPublishService,notificationService);
+ portListener.setLockManager(lockManager);
+ nvManager.setLockManager(lockManager);
+ l2GatewayProvider = new L2GatewayProvider(dbx, rpcProviderRegistry, entityOwnershipService);
+
+ LOG.info("NeutronvpnProvider Session Initiated");
+ } catch (Exception e) {
+ LOG.error("Error initializing services", e);
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ portListener.close();
+ subnetListener.close();
+ routerListener.close();
+ networkListener.close();
+ bgpvpnListener.close();
+ nvManager.close();
+ l2GatewayProvider.close();
+ LOG.info("NeutronvpnProvider Closed");
+ }
+
+ @Override
+ public List<String> showNeutronPortsCLI() {
+ return nvManager.showNeutronPortsCLI();
+ }
+
+ @Override
+ public List<String> showVpnConfigCLI(Uuid vuuid) {
+ return nvManager.showVpnConfigCLI(vuuid);
+ }
+
+ @Override
+ public void addSubnetToVpn(Uuid vpnId, Uuid subnet) {
+ nvManager.addSubnetToVpn(vpnId, subnet);
+ }
+
+ @Override
+ public List<Uuid> getSubnetsforVpn(Uuid vpnid) {
+ return nvManager.getSubnetsforVpn(vpnid);
+ }
+
+ @Override
+ public void removeSubnetFromVpn(Uuid vpnId, Uuid subnet) {
+ nvManager.removeSubnetFromVpn(vpnId, subnet);
+ }
+
+ @Override
+ public Port getNeutronPort(String name) {
+ return nvManager.getNeutronPort(name);
+ }
+
+ @Override
+ public Port getNeutronPort(Uuid portId) {
+ return nvManager.getNeutronPort(portId);
+ }
+
+ @Override
+ public Subnet getNeutronSubnet(Uuid subnetId) {
+ return nvManager.getNeutronSubnet(subnetId);
+ }
+
+ @Override
+ public String uuidToTapPortName(Uuid id) {
+ return NeutronvpnUtils.uuidToTapPortName(id);
+ }
+
+ @Override
+ public IpAddress getNeutronSubnetGateway(Uuid subnetId) {
+ return nvManager.getNeutronSubnetGateway(subnetId);
+ }
+
+}
--- /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.neutronvpn;
+
+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.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
+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.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.RouterKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.Networks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.NetworkKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.neutron.networks.network.Segments;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.TimeUnits;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.TryLockInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.TryLockInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.UnlockInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.UnlockInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.NetworkMaps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.NeutronPortData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.Subnetmaps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.VpnMaps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.networkmaps.NetworkMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.networkmaps.NetworkMapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.neutron.port.data
+ .PortFixedipToPortName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.neutron.port.data
+ .PortFixedipToPortNameKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.Subnetmap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.vpnmaps.VpnMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.vpnmaps.VpnMapKey;
+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 java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class NeutronvpnUtils {
+
+ private static final Logger logger = LoggerFactory.getLogger(NeutronvpnUtils.class);
+ public static final String VNIC_TYPE_NORMAL = "normal";
+
+ protected static Subnetmap getSubnetmap(DataBroker broker, Uuid subnetId) {
+ InstanceIdentifier id = buildSubnetMapIdentifier(subnetId);
+ Optional<Subnetmap> sn = read(broker, LogicalDatastoreType.CONFIGURATION, id);
+
+ if (sn.isPresent()) {
+ return sn.get();
+ }
+ return null;
+ }
+
+ protected static VpnMap getVpnMap(DataBroker broker, Uuid id) {
+ InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class).child(VpnMap.class,
+ new VpnMapKey(id)).build();
+ Optional<VpnMap> optionalVpnMap = read(broker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
+ if (optionalVpnMap.isPresent()) {
+ return optionalVpnMap.get();
+ }
+ logger.error("getVpnMap failed, VPN {} not present", id.getValue());
+ return null;
+ }
+
+ protected static Uuid getVpnForNetwork(DataBroker broker, Uuid network) {
+ InstanceIdentifier<VpnMaps> vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build();
+ Optional<VpnMaps> optionalVpnMaps = read(broker, LogicalDatastoreType.CONFIGURATION, vpnMapsIdentifier);
+ if (optionalVpnMaps.isPresent() && optionalVpnMaps.get().getVpnMap() != null) {
+ List<VpnMap> allMaps = optionalVpnMaps.get().getVpnMap();
+ for (VpnMap vpnMap : allMaps) {
+ List<Uuid> netIds = vpnMap.getNetworkIds();
+ if ((netIds != null) && (netIds.contains(network))) {
+ return vpnMap.getVpnId();
+ }
+ }
+ }
+ return null;
+ }
+
+ // true for external vpn, false for internal vpn
+ protected static Uuid getVpnForRouter(DataBroker broker, Uuid routerId, Boolean externalVpn) {
+ InstanceIdentifier<VpnMaps> vpnMapsIdentifier = InstanceIdentifier.builder(VpnMaps.class).build();
+ Optional<VpnMaps> optionalVpnMaps = read(broker, LogicalDatastoreType.CONFIGURATION,
+ vpnMapsIdentifier);
+ if (optionalVpnMaps.isPresent() && optionalVpnMaps.get().getVpnMap() != null) {
+ List<VpnMap> allMaps = optionalVpnMaps.get().getVpnMap();
+ if (routerId != null) {
+ for (VpnMap vpnMap : allMaps) {
+ if (routerId.equals(vpnMap.getRouterId())) {
+ if (externalVpn == true) {
+ if (!routerId.equals(vpnMap.getVpnId())) {
+ return vpnMap.getVpnId();
+ }
+ } else {
+ if (routerId.equals(vpnMap.getVpnId())) {
+ return vpnMap.getVpnId();
+ }
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ protected static Uuid getRouterforVpn(DataBroker broker, Uuid vpnId) {
+ InstanceIdentifier<VpnMap> vpnMapIdentifier = InstanceIdentifier.builder(VpnMaps.class)
+ .child(VpnMap.class, new VpnMapKey(vpnId)).build();
+ Optional<VpnMap> optionalVpnMap = read(broker, LogicalDatastoreType.CONFIGURATION, vpnMapIdentifier);
+ if (optionalVpnMap.isPresent()) {
+ VpnMap vpnMap = optionalVpnMap.get();
+ return vpnMap.getRouterId();
+ }
+ return null;
+ }
+
+ protected static String getNeutronPortNamefromPortFixedIp(DataBroker broker, String fixedIp) {
+ InstanceIdentifier id = buildFixedIpToPortNameIdentifier(fixedIp);
+ Optional<PortFixedipToPortName> portFixedipToPortNameData = read(broker, LogicalDatastoreType.CONFIGURATION,
+ id);
+ if (portFixedipToPortNameData.isPresent()) {
+ return portFixedipToPortNameData.get().getPortName();
+ }
+ return null;
+ }
+
+ protected static List<Uuid> getSubnetIdsFromNetworkId(DataBroker broker, Uuid networkId) {
+ InstanceIdentifier id = buildNetworkMapIdentifier(networkId);
+ Optional<NetworkMap> optionalNetworkMap = read(broker, LogicalDatastoreType.CONFIGURATION, id);
+ if (optionalNetworkMap.isPresent()) {
+ return optionalNetworkMap.get().getSubnetIdList();
+ }
+ return null;
+ }
+
+ protected static Router getNeutronRouter(DataBroker broker, Uuid routerId) {
+
+ InstanceIdentifier<Router> inst = InstanceIdentifier.create(Neutron.class).child(Routers.class).child(Router
+ .class, new RouterKey(routerId));
+ Optional<Router> rtr = read(broker, LogicalDatastoreType.CONFIGURATION, inst);
+ if (rtr.isPresent()) {
+ return rtr.get();
+ }
+ return null;
+ }
+
+ protected static Network getNeutronNetwork(DataBroker broker, Uuid networkId) {
+ logger.debug("getNeutronNetwork for {}", networkId.getValue());
+ InstanceIdentifier<Network> inst = InstanceIdentifier.create(Neutron.class).child(Networks.class).child
+ (Network.class, new NetworkKey(networkId));
+ Optional<Network> net = read(broker, LogicalDatastoreType.CONFIGURATION, inst);
+ if (net.isPresent()) {
+ return net.get();
+ }
+ return null;
+ }
+
+ protected static List<Uuid> getNeutronRouterSubnetIds(DataBroker broker, Uuid routerId) {
+ logger.info("getNeutronRouterSubnetIds for {}", routerId.getValue());
+
+ List<Uuid> subnetIdList = new ArrayList<Uuid>();
+ Router router = getNeutronRouter(broker, routerId);
+ if (router != null) {
+ List<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.router
+ .Interfaces> interfacesList = router.getInterfaces();
+ if (interfacesList != null) {
+ for (org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers
+ .router.Interfaces interfaces : interfacesList) {
+ subnetIdList.add(interfaces.getSubnetId());
+ }
+ }
+ }
+ logger.info("returning from getNeutronRouterSubnetIds for {}", routerId.getValue());
+ return subnetIdList;
+ }
+
+ protected static Port getNeutronPort(DataBroker broker, Uuid portId) {
+ logger.debug("getNeutronPort for {}", portId.getValue());
+ InstanceIdentifier<Port> inst = InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class,
+ new PortKey(portId));
+ Optional<Port> port = read(broker, LogicalDatastoreType.CONFIGURATION, inst);
+ if (port.isPresent()) {
+ return port.get();
+ }
+ return null;
+ }
+
+ protected static String uuidToTapPortName(Uuid id) {
+ String tapId = id.getValue().substring(0, 11);
+ return new StringBuilder().append("tap").append(tapId).toString();
+ }
+
+ protected static boolean lock(LockManagerService lockManager, String lockName) {
+ TryLockInput input = new TryLockInputBuilder().setLockName(lockName).setTime(5L).setTimeUnit
+ (TimeUnits.Milliseconds).build();
+ boolean islockAcquired = false;
+ try {
+ Future<RpcResult<Void>> result = lockManager.tryLock(input);
+ if ((result != null) && (result.get().isSuccessful())) {
+ logger.debug("Acquired lock for {}", lockName);
+ islockAcquired = true;
+ } else {
+ logger.error("Unable to acquire lock for {}", lockName);
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ logger.error("Unable to acquire lock for {}", lockName);
+ throw new RuntimeException(String.format("Unable to acquire lock for %s", lockName), e.getCause());
+ }
+ return islockAcquired;
+ }
+
+ protected static boolean unlock(LockManagerService lockManager, String lockName) {
+ UnlockInput input = new UnlockInputBuilder().setLockName(lockName).build();
+ boolean islockAcquired = false;
+ try {
+ Future<RpcResult<Void>> result = lockManager.unlock(input);
+ if ((result != null) && (result.get().isSuccessful())) {
+ logger.debug("Unlocked {}", lockName);
+ islockAcquired = true;
+ } else {
+ logger.error("Unable to unlock {}", lockName);
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ logger.error("Unable to unlock {}", lockName);
+ throw new RuntimeException(String.format("Unable to unlock %s", lockName), e.getCause());
+ }
+ return islockAcquired;
+ }
+
+ protected static Short getIPPrefixFromPort(DataBroker broker, Port port) {
+ Short prefix = new Short((short) 0);
+ String cidr = "";
+ try {
+ Uuid subnetUUID = port.getFixedIps().get(0).getSubnetId();
+
+ SubnetKey subnetkey = new SubnetKey(subnetUUID);
+ InstanceIdentifier<Subnet> subnetidentifier = InstanceIdentifier.create(Neutron.class).child(Subnets
+ .class).child(Subnet.class, subnetkey);
+ Optional<Subnet> subnet = read(broker, LogicalDatastoreType.CONFIGURATION,subnetidentifier);
+ if (subnet.isPresent()) {
+ cidr = subnet.get().getCidr();
+ // Extract the prefix length from cidr
+ String[] parts = cidr.split("/");
+ if ((parts.length == 2)) {
+ prefix = Short.valueOf(parts[1]);
+ return prefix;
+ } else {
+ logger.trace("Could not retrieve prefix from subnet CIDR");
+ System.out.println("Could not retrieve prefix from subnet CIDR");
+ }
+ } else {
+ logger.trace("Unable to read on subnet datastore");
+ }
+ } catch (Exception e) {
+ logger.error("Failed to retrieve IP prefix from port : ", e);
+ System.out.println("Failed to retrieve IP prefix from port : " + e.getMessage());
+ }
+ return null;
+ }
+
+ static InstanceIdentifier<PortFixedipToPortName> buildFixedIpToPortNameIdentifier(String fixedIp) {
+ InstanceIdentifier<PortFixedipToPortName> id = InstanceIdentifier.builder(NeutronPortData.class).child
+ (PortFixedipToPortName.class, new PortFixedipToPortNameKey(fixedIp)).build();
+ return id;
+ }
+
+ static InstanceIdentifier<NetworkMap> buildNetworkMapIdentifier(Uuid networkId) {
+ InstanceIdentifier<NetworkMap> id = InstanceIdentifier.builder(NetworkMaps.class).child(NetworkMap.class, new
+ NetworkMapKey(networkId)).build();
+ return id;
+ }
+
+ static InstanceIdentifier<VpnInterface> buildVpnInterfaceIdentifier(String ifName) {
+ InstanceIdentifier<VpnInterface> id = InstanceIdentifier.builder(VpnInterfaces.class).
+ child(VpnInterface.class, new VpnInterfaceKey(ifName)).build();
+ return id;
+ }
+
+ static InstanceIdentifier<Subnetmap> buildSubnetMapIdentifier(Uuid subnetId) {
+ InstanceIdentifier<Subnetmap> id = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new
+ SubnetmapKey(subnetId)).build();
+ return id;
+ }
+
+ static InstanceIdentifier<Interface> buildVlanInterfaceIdentifier(String interfaceName) {
+ InstanceIdentifier<Interface> id = InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new
+ InterfaceKey(interfaceName)).build();
+ return id;
+ }
+
+ 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;
+ }
+}
--- /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.neutronvpn.l2gw;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+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.controller.md.sal.binding.api.ClusteredDataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.vpnservice.utils.clustering.ClusteringUtils;
+import org.opendaylight.vpnservice.datastoreutils.AsyncClusteredDataChangeListenerBase;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.utils.L2GatewayCacheUtils;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepSouthboundConstants;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepSouthboundUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateway.attributes.Devices;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateways.attributes.L2gateways;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l2gateways.rev150712.l2gateways.attributes.l2gateways.L2gateway;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
+public class L2GatewayListener extends AsyncClusteredDataChangeListenerBase<L2gateway, L2GatewayListener>
+ implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(L2GatewayListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private ItmRpcService itmRpcService;
+ private EntityOwnershipService entityOwnershipService;
+
+ public L2GatewayListener(final DataBroker db, RpcProviderRegistry rpcRegistry,
+ EntityOwnershipService entityOwnershipService) {
+ super(L2gateway.class, L2GatewayListener.class);
+ broker = db;
+ this.entityOwnershipService = entityOwnershipService;
+ itmRpcService = rpcRegistry.getRpcService(ItmRpcService.class);
+ registerListener(db);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("L2 Gateway listener Closed");
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.create(Neutron.class).child(L2gateways.class).child(L2gateway.class),
+ L2GatewayListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("Neutron Manager L2 Gateway DataChange listener registration fail!", e);
+ throw new IllegalStateException("Neutron Manager L2 Gateway DataChange listener registration failed.", e);
+ }
+ }
+
+ @Override
+ protected void add(final InstanceIdentifier<L2gateway> identifier, final L2gateway input) {
+ LOG.info("Adding L2gateway with ID: {}", input.getUuid());
+
+ List<Devices> l2Devices = input.getDevices();
+ for (Devices l2Device : l2Devices) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Adding L2gateway device: {}", l2Device);
+ }
+ addL2Device(l2Device, input);
+ }
+ }
+
+ @Override
+ protected void remove(final InstanceIdentifier<L2gateway> identifier, final L2gateway input) {
+ LOG.info("Removing L2gateway with ID: {}", input.getUuid());
+
+ List<Devices> l2Devices = input.getDevices();
+ for (Devices l2Device : l2Devices) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Removing L2gateway device: {}", l2Device);
+ }
+ removeL2Device(l2Device, input);
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<L2gateway> identifier, L2gateway original, L2gateway update) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Updating L2gateway : key: " + identifier + ", original value=" + original + ", update value="
+ + update);
+ }
+ }
+
+ private void addL2Device(Devices l2Device, L2gateway input) {
+ final String l2DeviceName = l2Device.getDeviceName();
+ L2GatewayDevice l2GwDevice = L2GatewayCacheUtils.getL2DeviceFromCache(l2DeviceName);
+ if (l2GwDevice != null) {
+ if (!L2GatewayUtils.isGatewayAssociatedToL2Device(l2GwDevice)
+ && L2GatewayUtils.isL2GwDeviceConnected(l2GwDevice)) {
+ // VTEP already discovered; create ITM tunnels
+ final String hwvtepId = l2GwDevice.getHwvtepNodeId();
+ InstanceIdentifier<Node> iid = HwvtepSouthboundUtils.createInstanceIdentifier(new NodeId(hwvtepId));
+ ListenableFuture<Boolean> checkEntityOwnerFuture = ClusteringUtils.checkNodeEntityOwner(
+ entityOwnershipService, HwvtepSouthboundConstants.ELAN_ENTITY_TYPE,
+ HwvtepSouthboundConstants.ELAN_ENTITY_NAME);
+ final List<IpAddress> tunnelIps = l2GwDevice.getTunnelIps();
+ Futures.addCallback(checkEntityOwnerFuture, new FutureCallback<Boolean>() {
+ @Override
+ public void onSuccess(Boolean isOwner) {
+ if (isOwner) {
+ LOG.info("Creating ITM Tunnels for {} connected to cluster node owner", l2DeviceName);
+ for (IpAddress tunnelIp : tunnelIps) {
+ L2GatewayUtils.createItmTunnels(itmRpcService, hwvtepId, l2DeviceName, tunnelIp);
+ }
+ } else {
+ LOG.info("ITM Tunnels are not created on the cluster node as this is not owner for {}",
+ l2DeviceName);
+ }
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ LOG.error("Failed to create ITM tunnels", error);
+ }
+ });
+ } else {
+ LOG.trace("ITM tunnels are already created for device {}", l2DeviceName);
+ }
+ } else {
+ LOG.trace("{} is not connected; ITM tunnels will be created when device comes up", l2DeviceName);
+ // Pre-provision scenario. Create L2GatewayDevice without VTEP
+ // details for pushing configurations as soon as device discovered
+ l2GwDevice = new L2GatewayDevice();
+ l2GwDevice.setDeviceName(l2DeviceName);
+ L2GatewayCacheUtils.addL2DeviceToCache(l2DeviceName, l2GwDevice);
+ }
+ l2GwDevice.addL2GatewayId(input.getUuid());
+ }
+
+ private void removeL2Device(Devices l2Device, L2gateway input) {
+ final String l2DeviceName = l2Device.getDeviceName();
+ L2GatewayDevice l2GwDevice = L2GatewayCacheUtils.getL2DeviceFromCache(l2DeviceName);
+ if (l2GwDevice != null) {
+ // Delete ITM tunnels if it's last Gateway deleted and device is connected
+ // Also, do not delete device from cache if it's connected
+ if (L2GatewayUtils.isLastL2GatewayBeingDeleted(l2GwDevice)) {
+ if (L2GatewayUtils.isL2GwDeviceConnected(l2GwDevice)) {
+ l2GwDevice.removeL2GatewayId(input.getUuid());
+ // Delete ITM tunnels
+ final String hwvtepId = l2GwDevice.getHwvtepNodeId();
+ InstanceIdentifier<Node> iid = HwvtepSouthboundUtils.createInstanceIdentifier(new NodeId(hwvtepId));
+ ListenableFuture<Boolean> checkEntityOwnerFuture = ClusteringUtils.checkNodeEntityOwner(
+ entityOwnershipService, HwvtepSouthboundConstants.ELAN_ENTITY_TYPE,
+ HwvtepSouthboundConstants.ELAN_ENTITY_NAME);
+ final List<IpAddress> tunnelIps = l2GwDevice.getTunnelIps();
+ Futures.addCallback(checkEntityOwnerFuture, new FutureCallback<Boolean>() {
+ @Override
+ public void onSuccess(Boolean isOwner) {
+ if (isOwner) {
+ LOG.info("Deleting ITM Tunnels for {} connected to cluster node owner", l2DeviceName);
+ for (IpAddress tunnelIp : tunnelIps) {
+ L2GatewayUtils.deleteItmTunnels(itmRpcService, hwvtepId, l2DeviceName, tunnelIp);
+ }
+ } else {
+ LOG.info("ITM Tunnels are not deleted on the cluster node as this is not owner for {}",
+ l2DeviceName);
+ }
+ }
+
+ @Override
+ public void onFailure(Throwable error) {
+ LOG.error("Failed to delete ITM tunnels", error);
+ }
+ });
+ } else {
+ L2GatewayCacheUtils.removeL2DeviceFromCache(l2DeviceName);
+ }
+ } else {
+ l2GwDevice.removeL2GatewayId(input.getUuid());
+ LOG.trace("ITM tunnels are not deleted for {} as this device has other L2gateway associations",
+ l2DeviceName);
+ }
+ } else {
+ LOG.error("Unable to find L2 Gateway details for {}", l2DeviceName);
+ }
+ }
+
+ @Override
+ protected InstanceIdentifier<L2gateway> getWildCardPath() {
+ return InstanceIdentifier.create(L2gateway.class);
+ }
+
+ @Override
+ protected ClusteredDataChangeListener getDataChangeListener() {
+ return L2GatewayListener.this;
+ }
+
+ @Override
+ protected DataChangeScope getDataChangeScope() {
+ return AsyncDataBroker.DataChangeScope.BASE;
+ }
+}
--- /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.neutronvpn.l2gw;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.utils.L2GatewayCacheUtils;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class L2GatewayProvider {
+ private static final Logger LOG = LoggerFactory.getLogger(L2GatewayProvider.class);
+
+ private L2GatewayListener l2GatewayListener;
+
+ public L2GatewayProvider(DataBroker broker, RpcProviderRegistry rpcRegistry,
+ EntityOwnershipService entityOwnershipService) {
+ L2GatewayCacheUtils.createL2DeviceCache();
+ l2GatewayListener = new L2GatewayListener(broker, rpcRegistry, entityOwnershipService);
+ LOG.info("L2GatewayProvider Initialized");
+ }
+
+ public void close() throws Exception {
+ l2GatewayListener.close();
+ LOG.info("L2GatewayProvider Closed");
+ }
+}
--- /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.neutronvpn.l2gw;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.vpnservice.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepSouthboundConstants;
+import org.opendaylight.vpnservice.utils.hwvtep.HwvtepSouthboundUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.AddL2GwDeviceInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.DeleteL2GwDeviceInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class L2GatewayUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(L2GatewayUtils.class);
+
+ protected static boolean isGatewayAssociatedToL2Device(L2GatewayDevice l2GwDevice) {
+ return (l2GwDevice.getL2GatewayIds().size() > 0);
+ }
+
+ protected static boolean isLastL2GatewayBeingDeleted(L2GatewayDevice l2GwDevice) {
+ return (l2GwDevice.getL2GatewayIds().size() == 1);
+ }
+
+ protected static boolean isL2GwDeviceConnected(L2GatewayDevice l2GwDevice) {
+ return (l2GwDevice.getHwvtepNodeId() != null);
+ }
+
+ protected static boolean isItmTunnelsCreatedForL2Device(L2GatewayDevice l2GwDevice) {
+ return (l2GwDevice.getHwvtepNodeId() != null && l2GwDevice.getL2GatewayIds().size() > 0);
+ }
+
+ protected static void createItmTunnels(ItmRpcService itmRpcService, String hwvtepId, String psName,
+ IpAddress tunnelIp) {
+ AddL2GwDeviceInputBuilder builder = new AddL2GwDeviceInputBuilder();
+ builder.setTopologyId(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID.getValue());
+ builder.setNodeId(HwvtepSouthboundUtils.createManagedNodeId(new NodeId(hwvtepId), psName).getValue());
+ builder.setIpAddress(tunnelIp);
+ try {
+ Future<RpcResult<Void>> result = itmRpcService.addL2GwDevice(builder.build());
+ RpcResult<Void> rpcResult = result.get();
+ if (rpcResult.isSuccessful()) {
+ LOG.info("Created ITM tunnels for {}", hwvtepId);
+ } else {
+ LOG.error("Failed to create ITM Tunnels: ", rpcResult.getErrors());
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("RPC to create ITM tunnels failed", e);
+ }
+ }
+
+ protected static void deleteItmTunnels(ItmRpcService itmRpcService, String hwvtepId, String psName,
+ IpAddress tunnelIp) {
+ DeleteL2GwDeviceInputBuilder builder = new DeleteL2GwDeviceInputBuilder();
+ builder.setTopologyId(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID.getValue());
+ builder.setNodeId(HwvtepSouthboundUtils.createManagedNodeId(new NodeId(hwvtepId), psName).getValue());
+ builder.setIpAddress(tunnelIp);
+ try {
+ Future<RpcResult<Void>> result = itmRpcService.deleteL2GwDevice(builder.build());
+ RpcResult<Void> rpcResult = result.get();
+ if (rpcResult.isSuccessful()) {
+ LOG.info("Deleted ITM tunnels for {}", hwvtepId);
+ } else {
+ LOG.error("Failed to delete ITM Tunnels: ", rpcResult.getErrors());
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("RPC to delete ITM tunnels failed", e);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.neutronvpn.impl.rev150325;
+
+import org.opendaylight.vpnservice.neutronvpn.NeutronvpnProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
+
+public class NeutronvpnImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.neutronvpn
+ .impl.rev150325.AbstractNeutronvpnImplModule {
+ public NeutronvpnImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight
+ .controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public NeutronvpnImplModule(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.neutronvpn.impl.rev150325.NeutronvpnImplModule 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() {
+ // TODO:implement
+ LockManagerService lockManagerService = getRpcRegistryDependency().getRpcService(LockManagerService.class);
+ NeutronvpnProvider provider = new NeutronvpnProvider(getRpcRegistryDependency(),
+ getNotificationPublishServiceDependency(),getNotificationServiceDependency());
+ provider.setMdsalManager(getMdsalutilDependency());
+ provider.setLockManager(lockManagerService);
+ provider.setEntityOwnershipService(getEntityOwnershipServiceDependency());
+ getBrokerDependency().registerProvider(provider);
+ return provider;
+ }
+
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: neutronvpn-impl yang module local name: neutronvpn-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Thu Jan 06 10:51:12 IST 2016
+*
+* 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.neutronvpn.impl.rev150325;
+public class NeutronvpnImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.neutronvpn.impl.rev150325.AbstractNeutronvpnImplModuleFactory {
+
+}
--- /dev/null
+module neutronvpn-impl {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:neutronvpn:impl";
+ prefix "neutronvpn-impl";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import neutronvpn-api { prefix neutronvpn-api; revision-date 2015-08-12;}
+ 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 odl-mdsalutil { prefix odl-mdsal; revision-date 2015-04-10;}
+ import opendaylight-entity-ownership-service { prefix eos; revision-date 2015-08-10;}
+
+ description
+ "Service definition for neutronvpn project";
+
+ revision "2015-03-25" {
+ description
+ "Initial revision";
+ }
+
+ identity neutronvpn-impl {
+ base config:module-type;
+ config:provided-service neutronvpn-api:neutronvpn-api;
+ config:java-name-prefix NeutronvpnImpl;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case neutronvpn-impl {
+ when "/config:modules/config:module/config:type = 'neutronvpn-impl'";
+ container broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-broker-osgi-registry;
+ }
+ }
+ }
+ container rpc-registry {
+ 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 notification-publish-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding-impl:binding-new-notification-publish-service;
+ }
+ }
+ }
+ container notification-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding-impl:binding-new-notification-service;
+ }
+ }
+ }
+
+ container entity-ownership-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity eos:entity-ownership-service;
+ }
+ }
+ }
+ }
+ }
+}
--- /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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>neutronvpn-shell</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>neutronvpn-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.console</artifactId>
+ <version>${karaf.shell.console.version}</version>
+ </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.vpnservice.neutronvpn.shell;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.vpnservice.neutronvpn.interfaces.INeutronVpnManager;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.CreateL3VPNInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.CreateL3VPNOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.DeleteL3VPNInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.DeleteL3VPNOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.NeutronvpnService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.createl3vpn.input.L3vpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.createl3vpn.input.L3vpnBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+@Command(scope = "vpnservice", name = "configure-l3vpn", description = "Create/Delete Neutron L3VPN")
+public class ConfigureL3VpnCommand extends OsgiCommandSupport {
+
+ final Logger Logger = LoggerFactory.getLogger(ConfigureL3VpnCommand.class);
+
+ private INeutronVpnManager neutronVpnManager;
+ private RpcProviderRegistry rpcProviderRegistry;
+ private NeutronvpnService neutronvpnService;
+
+ public void setNeutronVpnManager(INeutronVpnManager neutronVpnManager) {
+ this.neutronVpnManager = neutronVpnManager;
+ }
+
+ public void setRpcRegistry(RpcProviderRegistry rpcProviderRegistry) {
+ this.rpcProviderRegistry = rpcProviderRegistry;
+ }
+
+ @Option(name = "-op", aliases = {"--operation"}, description = "create-l3-vpn/delete-l3-vpn",
+ required = false, multiValued = false)
+ String op;
+
+ @Option(name = "-vid", aliases = {"--vpnid"}, description = "VPN ID", required = false, multiValued = false)
+ String vid;
+
+ @Option(name = "-n", aliases = {"--name"}, description = "VPN Name", required = false, multiValued = false)
+ String name;
+
+ @Option(name = "-tid", aliases = {"--tenantid"}, description = "Tenant ID", required = false, multiValued = false)
+ String tid;
+
+ @Option(name = "-rd", aliases = {"--rd"}, description = "Route Distinguisher", required = false, multiValued =
+ false)
+ String rd;
+
+ @Option(name = "-irt", aliases = {"--import-rts"}, description = "List of Import RTs", required = false,
+ multiValued = false)
+ String irt;
+
+ @Option(name = "-ert", aliases = {"--export-rts"}, description = "List of Export RTs", required = false,
+ multiValued = false)
+ String ert;
+
+ @Option(name = "-sid", aliases = {"--subnet-uuid"}, description = "List of Subnet IDs", required = false,
+ multiValued = false)
+ String sid;
+
+ @Override
+ protected Object doExecute() throws Exception {
+
+ if (rpcProviderRegistry != null) {
+ neutronvpnService = rpcProviderRegistry.getRpcService(NeutronvpnService.class);
+ if (neutronvpnService != null) {
+ if (op != null) {
+ switch (op) {
+ case "create-l3-vpn":
+ createL3VpnCLI();
+ break;
+ case "delete-l3-vpn":
+ deleteL3VpnCLI();
+ break;
+ default:
+ System.out.println("Invalid argument.");
+ System.out.println(getHelp(""));
+ break;
+ }
+ } else {
+ System.out.println("Too few arguments");
+ System.out.println(getHelp(""));
+ }
+ } else {
+ System.out.println("neutronvpnservice not initialized");
+ }
+ } else {
+ System.out.println("rpcProviderRegistryService not initialized");
+ }
+ return null;
+ }
+
+ public void createL3VpnCLI() {
+
+ if (vid == null) {
+ System.out.println("Please supply a valid VPN ID");
+ System.out.println(getHelp("create"));
+ return;
+ }
+
+ if (rd == null) {
+ System.out.println("Please supply a valid RD");
+ System.out.println(getHelp("create"));
+ return;
+ }
+
+ if (irt == null) {
+ System.out.println("Please supply a valid list of import RTs separated by {,}");
+ System.out.println(getHelp("create"));
+ return;
+ }
+
+ if (ert == null) {
+ System.out.println("Please supply a valid list of export RTs separated by {,}");
+ System.out.println(getHelp("create"));
+ return;
+ }
+
+ Uuid vuuid = new Uuid(vid);
+
+ try {
+ ArrayList<String> rdList = new ArrayList<String>(Arrays.asList(rd.split(",")));
+ ArrayList<String> irtList = new ArrayList<String>(Arrays.asList(irt.split(",")));
+ ArrayList<String> ertList = new ArrayList<String>(Arrays.asList(ert.split(",")));
+ Uuid tuuid = null;
+
+ if (tid != null) {
+ tuuid = new Uuid(tid);
+ }
+
+ List<L3vpn> l3vpns = new ArrayList<L3vpn>();
+ L3vpn l3vpn = new L3vpnBuilder().setId(vuuid).setName(name).setRouteDistinguisher(rdList).setImportRT
+ (irtList)
+ .setExportRT(ertList).setTenantId(tuuid).build();
+ l3vpns.add(l3vpn);
+ Future<RpcResult<CreateL3VPNOutput>> result =
+ neutronvpnService.createL3VPN(new CreateL3VPNInputBuilder().setL3vpn(l3vpns).build());
+ RpcResult<CreateL3VPNOutput> rpcResult = result.get();
+ if (rpcResult.isSuccessful()) {
+ System.out.println("L3VPN created successfully");
+ Logger.trace("createl3vpn: {}", result);
+ } else {
+ System.out.println("error populating createL3VPN : " + result.get().getErrors());
+ System.out.println(getHelp("create"));
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ Logger.error("error populating createL3VPN", e);
+ System.out.println("error populating createL3VPN : " + e.getMessage());
+ System.out.println(getHelp("create"));
+ }
+
+ try {
+ List<Uuid> sidList = new ArrayList<Uuid>();
+
+ if (sid != null) {
+ for (String sidStr : sid.split(",")) {
+ Uuid suuid = new Uuid(sidStr);
+ sidList.add(suuid);
+ }
+ }
+ for (Uuid subnet : sidList) {
+ neutronVpnManager.addSubnetToVpn(vuuid, subnet);
+ }
+
+ } catch (Exception e) {
+ Logger.error("error in adding subnet to VPN", e);
+ System.out.println("error in adding subnet to VPN : " + e.getMessage());
+ }
+ }
+
+ public void deleteL3VpnCLI() {
+
+ if (vid == null) {
+ System.out.println("Please supply a valid VPN ID");
+ System.out.println(getHelp("delete"));
+ return;
+ }
+ Uuid vpnid = new Uuid(vid);
+ try {
+ List<Uuid> sidList = neutronVpnManager.getSubnetsforVpn(vpnid);
+ if (sidList != null) {
+ for (Uuid subnet : sidList) {
+ neutronVpnManager.removeSubnetFromVpn(vpnid, subnet);
+ }
+ }
+ } catch (Exception e) {
+ Logger.error("error in deleting subnet from VPN", e);
+ System.out.println("error in deleting subnet from VPN : " + e.getMessage());
+ }
+
+ try {
+ List<Uuid> vpnIdList = new ArrayList<Uuid>();
+ vpnIdList.add(vpnid);
+
+ Future<RpcResult<DeleteL3VPNOutput>> result =
+ neutronvpnService.deleteL3VPN(new DeleteL3VPNInputBuilder().setId(vpnIdList).build());
+ RpcResult<DeleteL3VPNOutput> rpcResult = result.get();
+ if (rpcResult.isSuccessful()) {
+ System.out.println("L3VPN deleted successfully");
+ Logger.trace("deletel3vpn: {}", result);
+ } else {
+ System.out.println("error populating deleteL3VPN : " + result.get().getErrors());
+ System.out.println(getHelp("delete"));
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ Logger.error("error populating deleteL3VPN", e);
+ System.out.println("error populating deleteL3VPN : " + e.getMessage());
+ System.out.println(getHelp("delete"));
+ }
+ }
+
+ private String getHelp(String cmd) {
+ StringBuilder help = new StringBuilder("Usage:");
+ switch (cmd) {
+ case "create":
+ help.append("exec configure-vpn -op/--operation create-l3-vpn -vid/--vpnid <id>\n");
+ help.append("-rd/--rd <rd> -irt/--import-rts <irt1,irt2,..> -ert/--export-rts <ert1,ert2,..>\n");
+ help.append("[-sid/--subnet-uuid <subnet1,subnet2,..>]\n");
+ break;
+ case "delete":
+ help.append("exec configure-vpn -op/--operation delete-l3-vpn -vid/--vpnid <id> \n");
+ break;
+ case "":
+ help.append("exec configure-vpn -op/--operation create-l3-vpn -vid/--vpnid <id>\n");
+ help.append("-rd/--rd <rd> -irt/--import-rts <irt1,irt2,..> -ert/--export-rts <ert1,ert2,..>\n");
+ help.append("[-sid/--subnet-uuid <subnet1,subnet2,..>]\n");
+ help.append("exec configure-vpn -op/--operation delete-l3-vpn -vid/--vpnid <id> \n");
+ }
+ return help.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.neutronvpn.shell;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.vpnservice.neutronvpn.interfaces.INeutronVpnManager;
+
+@Command(scope = "vpnservice", name = "neutron-ports-show", description = "Displays neutron ports")
+public class ShowNeutronPortsCommand extends OsgiCommandSupport {
+ private INeutronVpnManager neutronVpnManager;
+
+ public void setNeutronVpnManager(INeutronVpnManager neutronVpnManager) {
+ this.neutronVpnManager = neutronVpnManager;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+ for (String p : neutronVpnManager.showNeutronPortsCLI()) {
+ System.out.println(p);
+ }
+ 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.neutronvpn.shell;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.apache.karaf.shell.console.OsgiCommandSupport;
+import org.opendaylight.vpnservice.neutronvpn.interfaces.INeutronVpnManager;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+
+@Command(scope = "vpnservice", name = "l3vpn-config-show", description = "Displays Neutron L3VPN configuration")
+public class ShowVpnConfigCommand extends OsgiCommandSupport {
+
+ @Option(name = "-vid", aliases = {"--vpnid"}, description = "VPN ID", required = false, multiValued = false)
+ String vid;
+
+ private INeutronVpnManager neutronVpnManager;
+
+ public void setNeutronVpnManager(INeutronVpnManager neutronVpnManager) {
+ this.neutronVpnManager = neutronVpnManager;
+ }
+
+ @Override
+ protected Object doExecute() throws Exception {
+
+ Uuid vuuid = null;
+ if (vid != null) {
+ vuuid = new Uuid(vid);
+ }
+
+ for (String p : neutronVpnManager.showVpnConfigCLI(vuuid)) {
+ System.out.println(p);
+ }
+ return null;
+ }
+}
--- /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
+-->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <reference id="neutronVpnManagerRef"
+ interface="org.opendaylight.vpnservice.neutronvpn.interfaces.INeutronVpnManager"
+ availability="optional"/>
+ <reference id="rpcRegistryRef" interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry"
+ availability="optional"/>
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+
+ <command>
+ <action class="org.opendaylight.vpnservice.neutronvpn.shell.ConfigureL3VpnCommand">
+ <property name="neutronVpnManager" ref="neutronVpnManagerRef"/>
+ <property name="rpcRegistry" ref="rpcRegistryRef"/>
+ </action>
+ </command>
+
+ <command>
+ <action class="org.opendaylight.vpnservice.neutronvpn.shell.ShowVpnConfigCommand">
+ <property name="neutronVpnManager" ref="neutronVpnManagerRef"/>
+ </action>
+ </command>
+
+ <command>
+ <action class="org.opendaylight.vpnservice.neutronvpn.shell.ShowNeutronPortsCommand">
+ <property name="neutronVpnManager" ref="neutronVpnManagerRef"/>
+ </action>
+ </command>
+
+ </command-bundle>
+
+</blueprint>
--- /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.odlparent</groupId>
+ <artifactId>odlparent</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>neutronvpn-aggregator</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <name>neutronvpn</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>neutronvpn-api</module>
+ <module>neutronvpn-impl</module>
+ <module>neutronvpn-shell</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>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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>binding-parent</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/binding-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>nexthopmgr-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.yangtools</groupId>
+ <artifactId>yang-common</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>
+ </dependencies>
+</project>
--- /dev/null
+
+
+module l3nexthop {
+ namespace "urn:opendaylight:vpnservice:l3nexthop";
+ prefix l3nexthop;
+
+ revision "2015-04-09" {
+ description "L3 NextHop module";
+ }
+
+ container l3nexthop {
+ config false;
+ list vpnNexthops{
+ key "vpnId";
+ leaf vpnId {type uint32;}
+ list vpnNexthop{
+ key "IpAddress";
+ leaf IpAddress {type string;}
+ leaf egressPointer {type uint32;}
+ }
+ }
+ list tunnelNexthops{
+ key "dpnId";
+ leaf dpnId {type uint64;}
+ list tunnelNexthop{
+ key "IpAddress";
+ leaf IpAddress {type string;}
+ leaf egressPointer {type uint32;}
+ }
+ }
+ }
+
+ rpc getEgressPointer {
+ description "returns egress pointer, an OF Group Id";
+ input {
+ leaf dpnId {type uint64;}
+ leaf vpnId { type uint32;} /* optional */
+ leaf ipPrefix {type string;}
+ leaf nexthopIp {type string;}
+ }
+ output {
+ leaf egressPointer {type uint32;}
+ leaf localDestination {type boolean;}
+ }
+ }
+
+ rpc removeLocalNextHop {
+ description "remove a local next hop";
+ input {
+ leaf dpnId {type uint64;}
+ leaf vpnId { type uint32;} /* optional */
+ leaf ipPrefix {type string;}
+ leaf nexthopIp {type string;}
+ }
+ }
+}
\ 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) 2015 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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>nexthopmgr-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>vpnmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>interfacemgr-api</artifactId>
+ <version>${project.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>idmanager-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>nexthopmgr-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mdsalutil-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright (c) 2015 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:nexthopmgr:impl?module=nexthopmgr-impl&revision=2015-03-25</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:mdsalutil:api?module=odl-mdsalutil&revision=2015-04-10</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:nexthopmgr:impl">prefix:nexthopmgr-impl</type>
+ <name>nexthopmgr-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>
+ <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>
+ <rpc-registry>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+ <name>binding-rpc-broker</name>
+ </rpc-registry>
+ </module>
+ </modules>
+ </data>
+ </configuration>
+</snapshot>
--- /dev/null
+/*
+ * Copyright (c) 2015 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.nexthopmgr;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * AbstractDataChangeListener implemented basic {@link DataChangeListener} processing for
+ * VPN related Data Objects.
+ */
+public abstract class AbstractDataChangeListener<T extends DataObject> implements DataChangeListener {
+
+ protected final Class<T> clazz;
+
+ public AbstractDataChangeListener(Class<T> clazz) {
+ this.clazz = Preconditions.checkNotNull(clazz, "Class can not be null!");
+ }
+
+ @Override
+ public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
+ Preconditions.checkNotNull(changeEvent,"Async ChangeEvent can not be null!");
+
+ /* All DataObjects for create */
+ final Map<InstanceIdentifier<?>, DataObject> createdData = changeEvent.getCreatedData() != null
+ ? changeEvent.getCreatedData() : Collections.<InstanceIdentifier<?>, DataObject>emptyMap();
+ /* All DataObjects for remove */
+ final Set<InstanceIdentifier<?>> removeData = changeEvent.getRemovedPaths() != null
+ ? changeEvent.getRemovedPaths() : Collections.<InstanceIdentifier<?>> emptySet();
+ /* All DataObjects for updates */
+ final Map<InstanceIdentifier<?>, DataObject> updateData = changeEvent.getUpdatedData() != null
+ ? changeEvent.getUpdatedData() : Collections.<InstanceIdentifier<?>, DataObject> emptyMap();
+ /* All Original DataObjects */
+ final Map<InstanceIdentifier<?>, DataObject> originalData = changeEvent.getOriginalData() != null
+ ? changeEvent.getOriginalData() : Collections.<InstanceIdentifier<?>, DataObject> emptyMap();
+
+ this.createData(createdData);
+ this.updateData(updateData, originalData);
+ this.removeData(removeData, originalData);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void createData(final Map<InstanceIdentifier<?>, DataObject> createdData) {
+ final Set<InstanceIdentifier<?>> keys = createdData.keySet() != null
+ ? createdData.keySet() : Collections.<InstanceIdentifier<?>> emptySet();
+ for (InstanceIdentifier<?> key : keys) {
+ if (clazz.equals(key.getTargetType())) {
+ InstanceIdentifier<T> createKeyIdent = key.firstIdentifierOf(clazz);
+ final Optional<DataObject> value = Optional.of(createdData.get(key));
+ if (value.isPresent()) {
+ this.add(createKeyIdent, (T)value.get());
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void updateData(final Map<InstanceIdentifier<?>, DataObject> updateData,
+ final Map<InstanceIdentifier<?>, DataObject> originalData) {
+
+ final Set<InstanceIdentifier<?>> keys = updateData.keySet() != null
+ ? updateData.keySet() : Collections.<InstanceIdentifier<?>> emptySet();
+ for (InstanceIdentifier<?> key : keys) {
+ if (clazz.equals(key.getTargetType())) {
+ InstanceIdentifier<T> updateKeyIdent = key.firstIdentifierOf(clazz);
+ final Optional<DataObject> value = Optional.of(updateData.get(key));
+ final Optional<DataObject> original = Optional.of(originalData.get(key));
+ if (value.isPresent() && original.isPresent()) {
+ this.update(updateKeyIdent, (T)original.get(), (T)value.get());
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void removeData(final Set<InstanceIdentifier<?>> removeData,
+ final Map<InstanceIdentifier<?>, DataObject> originalData) {
+
+ for (InstanceIdentifier<?> key : removeData) {
+ if (clazz.equals(key.getTargetType())) {
+ final InstanceIdentifier<T> ident = key.firstIdentifierOf(clazz);
+ final DataObject removeValue = originalData.get(key);
+ this.remove(ident, (T)removeValue);
+ }
+ }
+ }
+
+ protected abstract void remove(InstanceIdentifier<T> identifier, T del);
+
+ protected abstract void update(InstanceIdentifier<T> identifier, T original, T update);
+
+ protected abstract void add(InstanceIdentifier<T> identifier, T add);
+
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 2015 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.nexthopmgr;
+
+import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
+import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
+import org.opendaylight.vpnservice.mdsalutil.InstructionType;
+import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.FutureCallback;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
+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.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;
+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.idmanager.rev150403.ReleaseIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.tunnelnexthops.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.*;
+import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
+import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.ActionType;
+import org.opendaylight.vpnservice.mdsalutil.BucketInfo;
+import org.opendaylight.vpnservice.mdsalutil.GroupEntity;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.idmanager.IdManager;
+import java.util.concurrent.ExecutionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NexthopManager implements L3nexthopService, AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(NexthopManager.class);
+ private final DataBroker broker;
+ private IMdsalApiManager mdsalManager;
+ private IInterfaceManager interfaceManager;
+ private IdManagerService idManager;
+ private static final short LPORT_INGRESS_TABLE = 0;
+ private static final short LFIB_TABLE = 20;
+ private static final short FIB_TABLE = 21;
+ private static final short DEFAULT_FLOW_PRIORITY = 10;
+
+ private static final FutureCallback<Void> DEFAULT_CALLBACK =
+ new FutureCallback<Void>() {
+ public void onSuccess(Void result) {
+ LOG.debug("Success in Datastore write operation");
+ }
+ public void onFailure(Throwable error) {
+ LOG.error("Error in Datastore write operation", error);
+ };
+ };
+
+ /**
+ * Provides nexthop functions
+ * Creates group ID pool
+ *
+ * @param db - dataBroker reference
+ */
+ public NexthopManager(final DataBroker db) {
+ broker = db;
+ }
+
+ @Override
+ public void close() throws Exception {
+ LOG.info("NextHop Manager Closed");
+ }
+
+ public void setInterfaceManager(IInterfaceManager ifManager) {
+ this.interfaceManager = ifManager;
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ public void setIdManager(IdManagerService idManager) {
+ this.idManager = idManager;
+ }
+
+ protected void createNexthopPointerPool() {
+ CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
+ .setPoolName("nextHopPointerPool")
+ .setLow(150000L)
+ .setHigh(175000L)
+ .build();
+ //TODO: Error handling
+ Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
+ LOG.trace("NextHopPointerPool result : {}", result);
+ }
+
+
+ protected long getVpnId(String vpnName) {
+ InstanceIdentifierBuilder<VpnInstance> idBuilder = InstanceIdentifier.builder(VpnInstances.class)
+ .child(VpnInstance.class, new VpnInstanceKey(vpnName));
+
+ InstanceIdentifier<VpnInstance> id = idBuilder.build();
+ //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) {
+ String[] fields = ofPortId.split(":");
+ BigInteger dpn = new BigInteger(fields[1]);
+ LOG.debug("DpnId: {}", dpn);
+ return dpn;
+ }
+
+ protected long createNextHopPointer(String nexthopKey) {
+ AllocateIdInput getIdInput = new AllocateIdInputBuilder()
+ .setPoolName("nextHopPointerPool").setIdKey(nexthopKey)
+ .build();
+ //TODO: Proper error handling once IdManager code is complete
+ try {
+ Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
+ RpcResult<AllocateIdOutput> rpcResult = result.get();
+ return rpcResult.getResult().getIdValue();
+ } catch (NullPointerException | InterruptedException | ExecutionException e) {
+ LOG.trace("",e);
+ }
+ return 0;
+ }
+
+ public void createLocalNextHop(String ifName, String vpnName, String ipAddress, String macAddress) {
+ String nhKey = new String("nexthop." + vpnName + ipAddress);
+ long groupId = createNextHopPointer(nhKey);
+
+ long vpnId = getVpnId(vpnName);
+ BigInteger dpnId = interfaceManager.getDpnForInterface(ifName);
+ VpnNexthop nexthop = getVpnNexthop(vpnId, ipAddress, 0);
+ LOG.trace("nexthop: {}", nexthop);
+ if (nexthop == null) {
+ List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
+ List<ActionInfo> listActionInfo = interfaceManager.getInterfaceEgressActions(ifName);
+ BucketInfo bucket = new BucketInfo(listActionInfo);
+ // MAC re-write
+ if (macAddress != null) {
+ listActionInfo.add(0, new ActionInfo(ActionType.set_field_eth_dest, new String[]{macAddress}));
+ listActionInfo.add(0, new ActionInfo(ActionType.pop_mpls, new String[]{}));
+ } else {
+ //FIXME: Log message here.
+ LOG.debug("mac address for new local nexthop is null");
+ }
+ listBucketInfo.add(bucket);
+ GroupEntity groupEntity = MDSALUtil.buildGroupEntity(
+ dpnId, groupId, ipAddress, GroupTypes.GroupIndirect, listBucketInfo);
+
+ // install Group
+ mdsalManager.installGroup(groupEntity);
+
+ //update MD-SAL DS
+ addVpnNexthopToDS(vpnId, ipAddress, groupId);
+ } else {
+ //check update
+ }
+ }
+
+ public void createRemoteNextHop(String ifName, String ipAddress) {
+ String nhKey = new String("nexthop." + ifName + ipAddress);
+ long groupId = createNextHopPointer(nhKey);
+
+ BigInteger dpnId = interfaceManager.getDpnForInterface(ifName);
+ TunnelNexthop nexthop = getTunnelNexthop(dpnId, ipAddress);
+ if (nexthop == null) {
+ List<BucketInfo> listBucketInfo = new ArrayList<BucketInfo>();
+ List<ActionInfo> listActionInfo = interfaceManager.getInterfaceEgressActions(ifName);
+ BucketInfo bucket = new BucketInfo(listActionInfo);
+ // MAC re-write??
+ listBucketInfo.add(bucket);
+ GroupEntity groupEntity = MDSALUtil.buildGroupEntity(
+ dpnId, groupId, ipAddress, GroupTypes.GroupIndirect, listBucketInfo);
+ mdsalManager.installGroup(groupEntity);
+ //makeRemoteFlow(dpnId, ifName, NwConstants.ADD_FLOW);
+
+ //update MD-SAL DS
+ addTunnelNexthopToDS(dpnId, ipAddress, groupId);
+ } else {
+ //check update
+ }
+ }
+
+ private void makeRemoteFlow(BigInteger dpnId, String ifName, int addOrRemoveFlow) {
+ long portNo = 0;
+ String flowName = ifName;
+ String flowRef = getTunnelInterfaceFlowRef(dpnId, LPORT_INGRESS_TABLE, ifName);
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
+ if (NwConstants.ADD_FLOW == addOrRemoveFlow) {
+ portNo = interfaceManager.getPortForInterface(ifName);
+ matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {
+ dpnId, BigInteger.valueOf(portNo) }));
+ mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] {LFIB_TABLE}));
+ }
+
+ BigInteger COOKIE_VM_INGRESS_TABLE = new BigInteger("8000001", 16);
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, LPORT_INGRESS_TABLE, flowRef,
+ DEFAULT_FLOW_PRIORITY, flowName, 0, 0, COOKIE_VM_INGRESS_TABLE, matches, mkInstructions);
+
+ if (NwConstants.ADD_FLOW == addOrRemoveFlow) {
+ mdsalManager.installFlow(flowEntity);
+ } else {
+ mdsalManager.removeFlow(flowEntity);
+ }
+ }
+
+ private String getTunnelInterfaceFlowRef(BigInteger dpnId, short tableId, String ifName) {
+ return new StringBuilder().append(dpnId).append(tableId).append(ifName).toString();
+ }
+
+ protected void addVpnNexthopToDS(long vpnId, String ipPrefix, long egressPointer) {
+
+ InstanceIdentifierBuilder<VpnNexthops> idBuilder = InstanceIdentifier.builder(
+ L3nexthop.class)
+ .child(VpnNexthops.class, new VpnNexthopsKey(vpnId));
+
+ // Add nexthop to vpn node
+ VpnNexthop nh = new VpnNexthopBuilder().
+ setKey(new VpnNexthopKey(ipPrefix)).
+ setIpAddress(ipPrefix).
+ setEgressPointer(egressPointer).build();
+
+ InstanceIdentifier<VpnNexthop> id1 = idBuilder
+ .child(VpnNexthop.class, new VpnNexthopKey(ipPrefix)).build();
+ LOG.trace("Adding vpnnextHop {} to Operational DS", nh);
+ syncWrite(LogicalDatastoreType.OPERATIONAL, id1, nh, DEFAULT_CALLBACK);
+
+ }
+
+ private void addTunnelNexthopToDS(BigInteger dpnId, String ipPrefix, long egressPointer) {
+ InstanceIdentifierBuilder<TunnelNexthops> idBuilder = InstanceIdentifier.builder(L3nexthop.class)
+ .child(TunnelNexthops.class, new TunnelNexthopsKey(dpnId));
+
+ // Add nexthop to dpn node
+ TunnelNexthop nh = new TunnelNexthopBuilder().
+ setKey(new TunnelNexthopKey(ipPrefix)).
+ setIpAddress(ipPrefix).
+ setEgressPointer(egressPointer).build();
+
+ InstanceIdentifier<TunnelNexthop> id1 = idBuilder
+ .child(TunnelNexthop.class, new TunnelNexthopKey(ipPrefix)).build();
+ LOG.trace("Adding tunnelnextHop {} to Operational DS for a dpn node", nh);
+ asyncWrite(LogicalDatastoreType.OPERATIONAL, id1, nh, DEFAULT_CALLBACK);
+
+ }
+
+ protected VpnNexthop getVpnNexthop(long vpnId, String ipAddress, int retryCount) {
+
+ // check if vpn node is there
+ InstanceIdentifierBuilder<VpnNexthops> idBuilder =
+ InstanceIdentifier.builder(L3nexthop.class).child(VpnNexthops.class, new VpnNexthopsKey(vpnId));
+ InstanceIdentifier<VpnNexthops> id = idBuilder.build();
+ try {
+ for (int retry = 0; retry <= retryCount; retry++) {
+ Optional<VpnNexthops> vpnNexthops = read(LogicalDatastoreType.OPERATIONAL, id);
+ if (vpnNexthops.isPresent()) {
+
+ // get nexthops list for vpn
+ List<VpnNexthop> nexthops = vpnNexthops.get().getVpnNexthop();
+ for (VpnNexthop nexthop : nexthops) {
+ if (nexthop.getIpAddress().equals(ipAddress)) {
+ // return nexthop
+ LOG.trace("VpnNextHop : {}", nexthop);
+ return nexthop;
+ }
+ }
+ }
+ Thread.sleep(100L);
+ }
+ } catch (InterruptedException e) {
+ LOG.trace("", e);
+ }
+ // return null if not found
+ return null;
+ }
+
+ private TunnelNexthop getTunnelNexthop(BigInteger dpnId, String ipAddress) {
+
+ InstanceIdentifierBuilder<TunnelNexthops> idBuilder = InstanceIdentifier.builder(L3nexthop.class)
+ .child(TunnelNexthops.class, new TunnelNexthopsKey(dpnId));
+
+ // check if vpn node is there
+ InstanceIdentifier<TunnelNexthops> id = idBuilder.build();
+ Optional<TunnelNexthops> dpnNexthops = read(LogicalDatastoreType.OPERATIONAL, id);
+ if (dpnNexthops.isPresent()) {
+ List<TunnelNexthop> nexthops = dpnNexthops.get().getTunnelNexthop();
+ for (TunnelNexthop nexthop : nexthops) {
+ if (nexthop.getIpAddress().equals(ipAddress)) {
+ LOG.trace("TunnelNextHop : {}",nexthop);
+ return nexthop;
+ }
+ }
+ }
+ return null;
+ }
+
+ public long getNextHopPointer(BigInteger dpnId, long vpnId, String prefixIp, String nextHopIp) {
+ String endpointIp = interfaceManager.getEndpointIpForDpn(dpnId);
+ if (nextHopIp.equals(endpointIp)) {
+ VpnNexthop vpnNextHop = getVpnNexthop(vpnId, prefixIp, 0);
+ return vpnNextHop.getEgressPointer();
+ } else {
+ TunnelNexthop tunnelNextHop = getTunnelNexthop(dpnId, nextHopIp);
+ LOG.trace("NExtHopPointer : {}", tunnelNextHop.getEgressPointer());
+ return tunnelNextHop.getEgressPointer();
+ }
+ }
+
+ private void removeTunnelNexthopFromDS(BigInteger dpnId, String ipPrefix) {
+
+ InstanceIdentifierBuilder<TunnelNexthop> idBuilder = InstanceIdentifier.builder(L3nexthop.class)
+ .child(TunnelNexthops.class, new TunnelNexthopsKey(dpnId))
+ .child(TunnelNexthop.class, new TunnelNexthopKey(ipPrefix));
+ InstanceIdentifier<TunnelNexthop> id = idBuilder.build();
+ // remove from DS
+ LOG.trace("Removing tunnel next hop from datastore : {}", id);
+ delete(LogicalDatastoreType.OPERATIONAL, id);
+ }
+
+ private void removeVpnNexthopFromDS(long vpnId, String ipPrefix) {
+
+ InstanceIdentifierBuilder<VpnNexthop> idBuilder = InstanceIdentifier.builder(L3nexthop.class)
+ .child(VpnNexthops.class, new VpnNexthopsKey(vpnId))
+ .child(VpnNexthop.class, new VpnNexthopKey(ipPrefix));
+ InstanceIdentifier<VpnNexthop> id = idBuilder.build();
+ // remove from DS
+ LOG.trace("Removing vpn next hop from datastore : {}", id);
+ delete(LogicalDatastoreType.OPERATIONAL, id);
+ }
+
+
+ public void removeLocalNextHop(BigInteger dpnId, Long vpnId, String ipAddress) {
+
+ VpnNexthop nh = getVpnNexthop(vpnId, ipAddress, 0);
+ if (nh != null) {
+ // how to inform and remove dependent FIB entries??
+ // we need to do it before the group is removed
+ GroupEntity groupEntity = MDSALUtil.buildGroupEntity(
+ dpnId, nh.getEgressPointer(), ipAddress, GroupTypes.GroupIndirect, null);
+ // remove Group ...
+ mdsalManager.removeGroup(groupEntity);
+ //update MD-SAL DS
+ removeVpnNexthopFromDS(vpnId, ipAddress);
+ } else {
+ //throw error
+ LOG.error("removal of local next hop failed");
+ }
+
+ }
+
+ public void removeRemoteNextHop(BigInteger dpnId, String ifName, String ipAddress) {
+
+ TunnelNexthop nh = getTunnelNexthop(dpnId, ipAddress);
+ if (nh != null) {
+ // how to inform and remove dependent FIB entries??
+ // we need to do it before the group is removed
+
+ // remove Group ...
+ GroupEntity groupEntity = MDSALUtil.buildGroupEntity(
+ dpnId, nh.getEgressPointer(), ipAddress, GroupTypes.GroupIndirect, null);
+ // remove Group ...
+ mdsalManager.removeGroup(groupEntity);
+ //makeRemoteFlow(dpnId, ifName, NwConstants.DEL_FLOW);
+ //update MD-SAL DS
+ removeTunnelNexthopFromDS(dpnId, ipAddress);
+ } else {
+ //throw error
+ LOG.error("removal of remote next hop failed : dpnid : {}, ipaddress : {}", dpnId, ipAddress);
+ }
+
+ }
+
+ @Override
+ public Future<RpcResult<GetEgressPointerOutput>> getEgressPointer(
+ GetEgressPointerInput input) {
+
+ GetEgressPointerOutputBuilder output = new GetEgressPointerOutputBuilder();
+
+ String endpointIp = interfaceManager.getEndpointIpForDpn(input.getDpnId());
+ LOG.trace("getEgressPointer: input {}, endpointIp {}", input, endpointIp);
+ if (input.getNexthopIp() == null || input.getNexthopIp().equals(endpointIp)) {
+ VpnNexthop vpnNextHop = getVpnNexthop(input.getVpnId(), input.getIpPrefix(), 5);
+ output.setEgressPointer(vpnNextHop.getEgressPointer());
+ output.setLocalDestination(true);
+ } else {
+ TunnelNexthop tunnelNextHop = getTunnelNexthop(input.getDpnId(), input.getNexthopIp());
+ output.setEgressPointer(tunnelNextHop.getEgressPointer());
+ output.setLocalDestination(false);
+ }
+
+ RpcResultBuilder<GetEgressPointerOutput> rpcResultBuilder = RpcResultBuilder.success();
+ rpcResultBuilder.withResult(output.build());
+
+ return Futures.immediateFuture(rpcResultBuilder.build());
+
+ }
+
+ <T extends DataObject> Optional<T> read(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;
+ }
+
+ private <T extends DataObject> void asyncWrite(LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.merge(datastoreType, path, data, true);
+ Futures.addCallback(tx.submit(), callback);
+ }
+
+ private <T extends DataObject> void syncWrite(LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.merge(datastoreType, path, data, true);
+ tx.submit();
+ }
+
+ private <T extends DataObject> void delete(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.delete(datastoreType, path);
+ Futures.addCallback(tx.submit(), DEFAULT_CALLBACK);
+ }
+
+ @Override
+ public Future<RpcResult<Void>> removeLocalNextHop(RemoveLocalNextHopInput input) {
+ VpnNexthop vpnNextHop = getVpnNexthop(input.getVpnId(), input.getIpPrefix(), 0);
+ RpcResultBuilder<Void> rpcResultBuilder;
+ LOG.debug("vpnnexthop is: {}", vpnNextHop);
+ try {
+ removeLocalNextHop(input.getDpnId(),input.getVpnId(), input.getIpPrefix());
+ rpcResultBuilder = RpcResultBuilder.success();
+ }
+ catch(Exception e){
+ LOG.error("Removal of local next hop for vpnNextHop {} failed {}" ,vpnNextHop, e);
+ rpcResultBuilder = RpcResultBuilder.failed();
+ }
+ return Futures.immediateFuture(rpcResultBuilder.build());
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.nexthopmgr;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+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.vpnservice.nexthopmgr.NexthopManager;
+import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.L3nexthopService;
+import org.opendaylight.idmanager.IdManager;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NexthopmgrProvider implements BindingAwareProvider, AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NexthopmgrProvider.class);
+ private VpnInterfaceChangeListener vpnIfListener;
+ private OdlInterfaceChangeListener odlIfListener;
+ private NexthopManager nhManager;
+ private IMdsalApiManager mdsalManager;
+ private IInterfaceManager interfaceManager;
+ private IdManagerService idManager;
+ private RpcProviderRegistry rpcProviderRegistry;
+
+ public RpcProviderRegistry getRpcProviderRegistry() {
+ return rpcProviderRegistry;
+ }
+
+ public void setRpcProviderRegistry(RpcProviderRegistry rpcProviderRegistry) {
+ this.rpcProviderRegistry = rpcProviderRegistry;
+ }
+
+ @Override
+ public void onSessionInitiated(ProviderContext session) {
+ try {
+ final DataBroker dbx = session.getSALService(DataBroker.class);
+ nhManager = new NexthopManager(dbx);
+ vpnIfListener = new VpnInterfaceChangeListener(dbx, nhManager);
+ odlIfListener = new OdlInterfaceChangeListener(dbx, nhManager, interfaceManager);
+ idManager = rpcProviderRegistry.getRpcService(IdManagerService.class);
+ final BindingAwareBroker.RpcRegistration<L3nexthopService> rpcRegistration = getRpcProviderRegistry().addRpcImplementation(L3nexthopService.class, nhManager);
+ nhManager.setMdsalManager(mdsalManager);
+ nhManager.setInterfaceManager(interfaceManager);
+ nhManager.setIdManager(idManager);
+ nhManager.createNexthopPointerPool();
+ LOG.info("NexthopmgrProvider Session Initiated");
+ }
+ catch (Exception e)
+ {
+ LOG.error("Error initializing services", e);
+ }
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ public void setInterfaceManager(IInterfaceManager interfaceManager) {
+ this.interfaceManager = interfaceManager;
+ }
+
+ public NexthopmgrProvider(RpcProviderRegistry rpcRegistry) {
+ this.rpcProviderRegistry = rpcRegistry;
+ }
+
+ @Override
+ public void close() throws Exception {
+ vpnIfListener.close();
+ odlIfListener.close();
+ nhManager.close();
+ LOG.info("NexthopmgrProvider Closed");
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.nexthopmgr;
+
+
+import java.math.BigInteger;
+
+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.interfacemgr.interfaces.IInterfaceManager;
+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.inet.types.rev100924.IpAddress;
+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.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class OdlInterfaceChangeListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(OdlInterfaceChangeListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private NexthopManager nexthopManager;
+ private IInterfaceManager interfaceManager;
+
+
+ public OdlInterfaceChangeListener(final DataBroker db, NexthopManager nhm, IInterfaceManager ifManager) {
+ super(Interface.class);
+ broker = db;
+ nexthopManager = nhm;
+ interfaceManager = ifManager;
+ registerListener(db);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("odlInterface listener Closed");
+ }
+
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), OdlInterfaceChangeListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("Nexthop Manager Interfaces DataChange listener registration fail!", e);
+ throw new IllegalStateException("Nexthop Manager registration Listener failed.", e);
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Interface> identifier, Interface interfaceInfo) {
+ LOG.trace("Adding Interface : key: " + identifier + ", value=" + interfaceInfo );
+ // READ interface config information
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface intrf =
+ getInterfaceFromConfigDS(nexthopManager, new InterfaceKey(interfaceInfo.getName()));
+
+ if(intrf != null && intrf.getType().equals(Tunnel.class)){
+ IfTunnel intfData = intrf.getAugmentation(IfTunnel.class);
+ IpAddress gatewayIp = intfData.getTunnelGateway();
+ IpAddress remoteIp = (gatewayIp == null) ? intfData.getTunnelDestination() : gatewayIp;
+ nexthopManager.createRemoteNextHop(intrf.getName(), remoteIp.getIpv4Address().getValue());
+ }
+ }
+
+ private InstanceIdentifier<Interface> getWildCardPath() {
+ return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Interface> identifier,
+ Interface interfaceInfo) {
+ LOG.trace("Removing interface : key: " + identifier + ", value=" + interfaceInfo );
+ // READ interface config information
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface intrf =
+ getInterfaceFromConfigDS(nexthopManager, new InterfaceKey(interfaceInfo.getName()));
+
+ if (intrf != null && intrf.getType().equals(Tunnel.class)) {
+ BigInteger dpnId = interfaceManager.getDpnForInterface(intrf);
+ IfTunnel intfData = intrf.getAugmentation(IfTunnel.class);
+ IpAddress gatewayIp = intfData.getTunnelGateway();
+ IpAddress remoteIp = (gatewayIp == null) ? intfData.getTunnelDestination() : gatewayIp;
+ nexthopManager.removeRemoteNextHop(dpnId, intrf.getName(), remoteIp.getIpv4Address().getValue());
+ }
+ }
+
+ public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface getInterfaceFromConfigDS(NexthopManager nexthopManager, InterfaceKey interfaceKey) {
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface> interfaceId =
+ getInterfaceIdentifier(interfaceKey);
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface> interfaceOptional =
+ nexthopManager.read(LogicalDatastoreType.CONFIGURATION, interfaceId);
+ if (!interfaceOptional.isPresent()) {
+ return null;
+ }
+
+ return interfaceOptional.get();
+ }
+
+ public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface> getInterfaceIdentifier(InterfaceKey interfaceKey) {
+ InstanceIdentifier.InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface> interfaceInstanceIdentifierBuilder =
+ InstanceIdentifier.builder(Interfaces.class).child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface.class, interfaceKey);
+ return interfaceInstanceIdentifierBuilder.build();
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Interface> identifier,
+ Interface original, Interface update) {
+ // TODO Auto-generated method stub
+
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2015 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.nexthopmgr;
+
+import java.util.List;
+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.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.vpnservice.nexthopmgr.AbstractDataChangeListener;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class VpnInterfaceChangeListener extends AbstractDataChangeListener<Adjacencies> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceChangeListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private NexthopManager nexthopManager;
+
+ public VpnInterfaceChangeListener(final DataBroker db, NexthopManager nhm) {
+ super(Adjacencies.class);
+ broker = db;
+ nexthopManager = nhm;
+ registerListener(db);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("VPN Interface Manager Closed");
+ }
+
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), VpnInterfaceChangeListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("Nexthop Manager DataChange listener registration fail!", e);
+ throw new IllegalStateException("Nexthop Manager registration Listener failed.", e);
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Adjacencies> identifier,
+ Adjacencies adjs) {
+ LOG.trace("Adding adjacencies interface : key: " + identifier + ", value=" + adjs );
+ InstanceIdentifier<VpnInterface> vpnIfId = identifier.firstIdentifierOf(VpnInterface.class);
+ Optional<VpnInterface> vpnIf = read(LogicalDatastoreType.OPERATIONAL, vpnIfId);
+ VpnInterface vpnIfData = vpnIf.get();
+
+ List<Adjacency> adjList = adjs.getAdjacency();
+ for (Adjacency adjacency : adjList) {
+ nexthopManager.createLocalNextHop(
+ vpnIfData.getName(),
+ vpnIfData.getVpnInstanceName(),
+ adjacency.getIpAddress(),
+ adjacency.getMacAddress());
+ }
+ }
+
+
+ @Override
+ protected void remove(InstanceIdentifier<Adjacencies> identifier,
+ Adjacencies adjs) {
+ // nexthop group will be removed after fib entry deletion
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Adjacencies> identifier,
+ Adjacencies original, Adjacencies update) {
+ // TODO Auto-generated method stub
+ }
+
+
+ private <T extends DataObject> Optional<T> read(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;
+ }
+
+ private InstanceIdentifier<Adjacencies> getWildCardPath() {
+ return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class).augmentation(Adjacencies.class);
+ }
+
+
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nexthopmgr.impl.rev150325;
+
+import org.opendaylight.vpnservice.nexthopmgr.NexthopmgrProvider;
+
+public class NexthopmgrImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nexthopmgr.impl.rev150325.AbstractNexthopmgrImplModule {
+ public NexthopmgrImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public NexthopmgrImplModule(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.nexthopmgr.impl.rev150325.NexthopmgrImplModule 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() {
+ NexthopmgrProvider provider = new NexthopmgrProvider(getRpcRegistryDependency());
+ provider.setMdsalManager(getMdsalutilDependency());
+ provider.setInterfaceManager(getOdlinterfaceDependency());
+ getBrokerDependency().registerProvider(provider);
+ return provider;
+ }
+
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: nexthopmgr-impl yang module local name: nexthopmgr-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Wed Apr 01 23:18:39 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.nexthopmgr.impl.rev150325;
+public class NexthopmgrImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.nexthopmgr.impl.rev150325.AbstractNexthopmgrImplModuleFactory {
+
+}
--- /dev/null
+module nexthopmgr-impl {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:nexthopmgr:impl";
+ prefix "nexthopmgr-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 odl-mdsalutil { prefix odl-mdsal; revision-date 2015-04-10;}
+ import odl-interface {prefix odlif; revision-date 2015-03-31;}
+
+ description
+ "Service definition for nexthopmgr project";
+
+ revision "2015-03-25" {
+ description
+ "Initial revision";
+ }
+
+ identity nexthopmgr-impl {
+ base config:module-type;
+ config:java-name-prefix NexthopmgrImpl;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case nexthopmgr-impl {
+ when "/config:modules/config:module/config:type = 'nexthopmgr-impl'";
+ container broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-broker-osgi-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 rpc-registry {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-rpc-registry;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.nexthopmgr.test;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+class MockDataChangedEvent implements AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> {
+ Map<InstanceIdentifier<?>, DataObject> created = new HashMap<>();
+ Map<InstanceIdentifier<?>, DataObject> updated = new HashMap<>();
+ Map<InstanceIdentifier<?>, DataObject> original = new HashMap<>();
+ Set<InstanceIdentifier<?>> removed = new HashSet<>();
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
+ return created;
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getUpdatedData() {
+ return updated;
+ }
+
+ @Override
+ public Set<InstanceIdentifier<?>> getRemovedPaths() {
+ return removed;
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getOriginalData() {
+ return original;
+ }
+
+ @Override
+ public DataObject getOriginalSubtree() {
+ throw new UnsupportedOperationException("Not implemented by mock");
+ }
+
+ @Override
+ public DataObject getUpdatedSubtree() {
+ throw new UnsupportedOperationException("Not implemented by mock");
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.nexthopmgr.test;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+
+import java.math.BigInteger;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.L3nexthop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.VpnNexthopsKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+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.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.idmanager.IdManager;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.vpnservice.nexthopmgr.NexthopManager;
+import org.opendaylight.vpnservice.nexthopmgr.VpnInterfaceChangeListener;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
+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.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacenciesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.VpnNexthops;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.vpnnexthops.VpnNexthopBuilder;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
+
+@RunWith(MockitoJUnitRunner.class)
+public class NexthopManagerTest {
+
+ private final String ifName = "dpn1-if0";
+ private final String vpnName = "vpn1";
+ private final String ipAddress = "1.1.1.1";
+ private final String macAddress = "11:22:33:44:55:66";
+ private final int groupId = 5000;
+ private final BigInteger dpId = BigInteger.ONE;
+ private final long vpnId = 2L;
+
+ Map<InstanceIdentifier<?>, DataObject> written = new HashMap<>();
+ Map<InstanceIdentifier<?>, DataObject> updated = new HashMap<>();
+ Set<InstanceIdentifier<?>> removed = new HashSet<>();
+
+ @Mock
+ DataBroker dataBroker;
+ @Mock
+ IdManager idManager;
+ @Mock
+ IInterfaceManager interfacemanager;
+ @Mock
+ ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
+ @Mock
+ ReadOnlyTransaction mockReadTx;
+ @Mock
+ WriteTransaction mockWriteTx;
+ @Mock
+ IMdsalApiManager mdsalmanager;
+
+ MockDataChangedEvent dataChangeEvent;
+ NexthopManager nhmgr;
+ VpnInterfaceChangeListener vpnchglistener;
+ VpnInstance vpninstance;
+ VpnInterface vpninterface;
+ VpnNexthops vpnnexthops;
+ VpnNexthop vpnNexthop;
+
+ InstanceIdentifier<VpnInterface> vpnInterfaceIdent;
+ InstanceIdentifier<Adjacencies> adjacencies;
+ Adjacencies adjacency;
+ List<Adjacency> adjList = new ArrayList<Adjacency>();
+
+ Adjacency adjacencyobject = new Adjacency() {
+
+ @Override
+ public <E extends Augmentation<Adjacency>> E getAugmentation(Class<E> augmentationType) {
+ return null;
+ }
+
+ @Override
+ public Class<? extends DataContainer> getImplementedInterface() {
+ return null;
+ }
+
+ @Override
+ public String getNextHopIp() {
+ return null;
+ }
+
+ @Override
+ public String getMacAddress() {
+ return macAddress;
+ }
+
+ @Override
+ public Long getLabel() {
+ return null;
+ }
+
+ @Override
+ public AdjacencyKey getKey() {
+ return null;
+ }
+
+ @Override
+ public String getIpAddress() {
+ return ipAddress;
+ }
+ };
+
+ @Before
+ public void setUp() throws Exception {
+ adjacency = getVpnInterfaceAugmentation(adjList);
+ adjacencies =
+ InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class).augmentation(Adjacencies.class);
+ vpnInterfaceIdent = adjacencies.firstIdentifierOf(VpnInterface.class);
+ vpninterface = getVpnInterface(ifName, vpnName, adjacency);
+ adjList.add(adjacencyobject);
+
+ when(
+ dataBroker.registerDataChangeListener(any(LogicalDatastoreType.class), any(InstanceIdentifier.class),
+ any(DataChangeListener.class), any(DataChangeScope.class))).thenReturn(
+ dataChangeListenerRegistration);
+
+ dataChangeEvent = new MockDataChangedEvent();
+ vpnNexthop = new VpnNexthopBuilder().setEgressPointer(10L).setIpAddress(ipAddress).build();
+ nhmgr = new NexthopManager(dataBroker) {
+ protected long createNextHopPointer(String nexthopKey) {
+ return groupId;
+ }
+
+ protected long getVpnId(String vpnName) {
+ return vpnId;
+ }
+
+ protected VpnNexthop getVpnNexthop(long vpnId, String ipAddress) {
+ return vpnNexthop;
+ }
+
+ protected void addVpnNexthopToDS(long vpnId, String ipPrefix, long egressPointer) {
+ return;
+ }
+ };
+
+ nhmgr.setInterfaceManager(interfacemanager);
+ nhmgr.setMdsalManager(mdsalmanager);
+ vpnchglistener = new VpnInterfaceChangeListener(dataBroker, nhmgr);
+ setupMocks();
+ }
+
+ private void setupMocks() {
+ when(dataBroker.newReadOnlyTransaction()).thenReturn(mockReadTx);
+ when(dataBroker.newWriteOnlyTransaction()).thenReturn(mockWriteTx);
+ }
+
+ @Test
+ public void testAdd() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+ Optional<VpnInterface> vpnIf = Optional.of(vpninterface);
+
+ doReturn(Futures.immediateCheckedFuture(vpnIf)).when(mockReadTx).read(LogicalDatastoreType.OPERATIONAL,
+ vpnInterfaceIdent);
+ InstanceIdentifierBuilder<VpnNexthops> idBuilder =
+ InstanceIdentifier.builder(L3nexthop.class).child(VpnNexthops.class, new VpnNexthopsKey(vpnId));
+ InstanceIdentifier<VpnNexthops> id = idBuilder.build();
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(LogicalDatastoreType.OPERATIONAL,id);
+
+ when(interfacemanager.getDpnForInterface(ifName)).thenReturn(dpId);
+ dataChangeEvent.created.put(adjacencies, adjacency);
+ vpnchglistener.onDataChanged(dataChangeEvent);
+
+ // FIXME: Add some verifications
+ }
+
+ private Adjacencies getVpnInterfaceAugmentation(List<Adjacency> nextHops) {
+ return new AdjacenciesBuilder().setAdjacency(nextHops).build();
+ }
+
+ private VpnInterface getVpnInterface(String intfName, String vpnName, Adjacencies aug) {
+ return new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(intfName)).setVpnInstanceName(vpnName)
+ .addAugmentation(Adjacencies.class, aug).build();
+ }
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>nexthopmgr-aggregator</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <name>nexthopmgr</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>nexthopmgr-api</module>
+ <module>nexthopmgr-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>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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,
+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">
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>vpnservice</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <name>${project.artifactId}</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>commons/binding-parent</module>
+ <module>commons/config-parent</module>
+ <module>model-bgp</module>
+ <module>mdsalutil</module>
+ <module>lockmanager</module>
+ <module>idmanager</module>
+ <module>arputil</module>
+ <module>vpnmanager</module>
+ <module>interfacemgr</module>
+ <module>alivenessmonitor</module>
+ <module>elanmanager</module>
+ <module>fibmanager</module>
+ <module>bgpmanager</module>
+ <module>neutronvpn</module>
+ <module>dhcpservice</module>
+ <module>itm</module>
+ <module>natservice</module>
+ <module>distribution/karaf</module>
+ <module>features</module>
+ <module>vpnservice-artifacts</module>
+ <module>vpnintent</module>
+ <module>fcapsmanager</module>
+ <module>fcapsapplication</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>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/vpnservice.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/vpnservice.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/VPNService:Main</url>
+ <tag>HEAD</tag>
+ </scm>
+</project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2016 Inocybe Technologies 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>binding-parent</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/binding-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>vpnintent-api</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <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>
+ </dependencies>
+
+</project>
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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
+ */
+module vpnintent {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:vpnintent";
+ prefix "vpnintent";
+
+ import ietf-inet-types { prefix inet; revision-date 2010-09-24;}
+
+ revision "2015-01-05" {
+ description "Initial revision of VPN intent model.
+ Create VPN via Intent, keep VPN state and manage MPLS labels";
+ }
+
+ container vpns{
+ list vpn-intents {
+ key "vpn-name";
+ uses vpn-intent;
+ }
+ }
+
+ typedef failover-type {
+ type enumeration {
+ enum fast-reroute {
+ value 1;
+ }
+ enum slow-reroute {
+ value 2;
+ }
+ }
+ }
+
+ grouping vpn-intent {
+ leaf vpn-name {
+ type string;
+ description "VPN name";
+ mandatory true;
+ }
+ leaf path-protection {
+ type boolean;
+ }
+ leaf failover-type {
+ type failover-type;
+ }
+ list endpoint {
+ key "site-name";
+ uses endpoint-fields;
+ description "List to keep track site name and endpoint.";
+ }
+ }
+
+ grouping endpoint-fields {
+ leaf site-name{
+ type string;
+ description "VPN member site name.";
+ }
+
+ leaf ip-prefix {
+ type inet:ip-prefix;
+ description "VPN member IP prefix.";
+ }
+
+ leaf switch-port-id {
+ type string;
+ description "Switch and port ID that VPN member is connected to.";
+ }
+ }
+
+ grouping labels {
+ list label {
+ key "label-id";
+ leaf "label-id"{
+ type uint32 {
+ range "0 .. 524288";
+ }
+ description "20 bit MPLS label ID";
+ mandatory true;
+ }
+ uses endpoint-fields;
+ description "Keep track of MPLS/other label endpoint relation.";
+ }
+ }
+
+ container mpls-labels {
+ uses labels;
+ }
+
+ rpc add-vpn-endpoint{
+ description
+ "Add VPN endpoint.";
+ input {
+ leaf vpn-name {
+ type string;
+ description "VPN name";
+ mandatory true;
+ }
+ uses endpoint-fields;
+ }
+ }
+
+ rpc remove-vpn-endpoint{
+ description
+ "Remove VPN endpoint.";
+ input {
+ leaf vpn-name {
+ type string;
+ description "VPN name";
+ mandatory true;
+ }
+ leaf site-name{
+ type string;
+ description "VPN member site name.";
+ }
+ }
+ }
+
+ rpc remove-vpn{
+ description
+ "Remove VPN and its endpoints.";
+ input {
+ leaf vpn-name {
+ type string;
+ description "VPN name";
+ mandatory true;
+ }
+ }
+ }
+ }
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2016 Inocybe Technologies 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.vpnservice</groupId>
+ <artifactId>config-parent</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>vpnintent-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <nic.version>1.2.0-SNAPSHOT</nic.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>vpnintent-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- NIC dependency -->
+ <dependency>
+ <groupId>org.opendaylight.nic</groupId>
+ <artifactId>intent-api</artifactId>
+ <version>${nic.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.nic</groupId>
+ <artifactId>intent-mapping-interface</artifactId>
+ <version>${nic.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.nic</groupId>
+ <artifactId>utils</artifactId>
+ <version>${nic.version}</version>
+ </dependency>
+
+ <!-- Testing Dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright (c) 2016 Inocybe Technologies 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:vpnintent:impl?module=vpnintent-impl&revision=2014-12-10</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&revision=2013-10-28</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:vpnintent:impl">prefix:vpnintent-impl</type>
+ <name>vpnintent-impl-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>
+ <rpc-registry>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+ <name>binding-rpc-broker</name>
+ </rpc-registry>
+ </module>
+ </modules>
+ </data>
+ </configuration>
+</snapshot>
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.nic.utils.MdsalUtils;
+import org.opendaylight.vpnservice.utils.IidFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.constraints.rev150122.FailoverType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.Intents;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.IntentsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.Actions;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.ActionsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.Constraints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.ConstraintsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.Subjects;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.SubjectsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.action.allow.AllowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.action.block.BlockBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints.constraints.failover.constraint.FailoverConstraintBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints.constraints.protection.constraint.ProtectionConstraintBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.end.point.group.EndPointGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.end.point.group.EndPointGroupBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.Intent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.IntentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.IntentKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.types.rev150122.Uuid;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * This class is used to build Intents object and
+ * write it to Network Intent Composition md-sal tree
+ * in order to create/delete intents between two endpoint groups.
+ */
+public class IntentServiceManager {
+
+ private static final Logger LOG = LoggerFactory.getLogger(IntentServiceManager.class);
+ private static final short FIRST_SUBJECT = 1;
+ private static final short SECOND_SUBJECT = 2;
+ public static final String ACTION_ALLOW = "ALLOW";
+ public static final String ACTION_BLOCK = "BLOCK";
+ public static final String FAST_REROUTE = "fast-reroute";
+ public static final String SLOW_REROUTE = "slow-reroute";
+ private final DataBroker dataBroker;
+ private static final InstanceIdentifier<Intents> INTENTS_IID = IidFactory.getIntentsIid();
+ private final MdsalUtils mdsal;
+
+ public IntentServiceManager(DataBroker dataBroker) {
+ this.dataBroker = dataBroker;
+ this.mdsal = new MdsalUtils(dataBroker);
+ }
+
+ /**
+ * Create Intents object and write to to config tree to trigger intents
+ * @param src :Source Site Name
+ * @param dst :Destination Site Name
+ * @param intentAction :Intent verb: ALLOW or BLOCK
+ * @param failOverType
+ */
+ public void addIntent(String src, String dst, String intentAction, String failOverType) {
+ Preconditions.checkNotNull(src);
+ Preconditions.checkNotNull(dst);
+ Preconditions.checkNotNull(intentAction);
+
+ List<Intent> intentList = null;
+ List<Subjects> subjects = createSubjects(dst, src);
+ List<Actions> intentActions = createActions(intentAction);
+ List<Constraints> intentConstraints = createConstraints(failOverType);
+
+ Intent intent = new IntentBuilder().setId(new Uuid(UUID.randomUUID().toString()))
+ .setSubjects(subjects).setActions(intentActions)
+ .setConstraints(intentConstraints)
+ .build();
+
+ Intents currentIntents = mdsal.read(LogicalDatastoreType.CONFIGURATION, INTENTS_IID);
+ if (currentIntents == null) {
+ intentList = new ArrayList<>();
+ } else {
+ intentList = currentIntents.getIntent();
+ }
+ intentList.add(intent);
+ Intents intents = new IntentsBuilder().setIntent(intentList).build();
+ mdsal.put(LogicalDatastoreType.CONFIGURATION, INTENTS_IID, intents);
+ LOG.info("AddIntent: config populated: {}", intents);
+ }
+
+ /**
+ * Delete an Intent
+ * @param id :Uuid of the Intent to be deleted
+ */
+ public void removeIntent(Uuid id) {
+ Preconditions.checkNotNull(id);
+ InstanceIdentifier<Intent> iid = InstanceIdentifier.create(Intents.class).child(Intent.class, new IntentKey(id));
+ mdsal.delete(LogicalDatastoreType.CONFIGURATION, iid);
+ LOG.info("RemoveIntent succeeded");
+ }
+
+ /**
+ * Remove all associated intents by endpointGroupName
+ * @param endpointGroupName
+ */
+ public void removeIntentsByEndpoint(String endpointGroupName) {
+ Preconditions.checkNotNull(endpointGroupName);
+
+ Intents intents = mdsal.read(LogicalDatastoreType.CONFIGURATION, INTENTS_IID);
+
+ if (intents != null && intents.getIntent() != null) {
+ for (Intent intent : intents.getIntent()) {
+ if (intent.getSubjects() != null && intent.getSubjects().size() > 0) {
+ String endpointValue = "";
+ for (Subjects subject : intent.getSubjects()) {
+ if (subject
+ .getSubject() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup) {
+ org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup epg = (org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup) subject
+ .getSubject();
+ endpointValue = epg.getEndPointGroup().getName();
+ } else if (subject
+ .getSubject() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointSelector) {
+ org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointSelector epg = (org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointSelector) subject
+ .getSubject();
+ endpointValue = epg.getEndPointSelector().getEndPointSelector();
+ } else if (subject
+ .getSubject() instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroupSelector) {
+ org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroupSelector epg = (org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroupSelector) subject
+ .getSubject();
+ endpointValue = epg.getEndPointGroupSelector().getEndPointGroupSelector();
+ }
+ if (endpointValue.equalsIgnoreCase(endpointGroupName)) {
+ removeIntent(intent.getId());
+ LOG.info("Deleted Intent ID : {} for endpoint: {}", intent.getId(), endpointGroupName);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Create a list of Intent actions
+ * @param intentAction
+ * @return :a list of Actions
+ */
+ private List<Actions> createActions(String intentAction) {
+ List<Actions> actionsList = new ArrayList<Actions>();
+ short order = 1;
+ org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.Action action = null;
+ if (intentAction.equalsIgnoreCase(ACTION_ALLOW)) {
+ action = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.action
+ .AllowBuilder().setAllow(new AllowBuilder().build()).build();
+ } else if (intentAction.equalsIgnoreCase(ACTION_BLOCK)) {
+ action = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.actions.action
+ .BlockBuilder().setBlock(new BlockBuilder().build()).build();
+ }
+
+ Actions intentActions = new ActionsBuilder().setOrder(order).setAction(action).build();
+ actionsList.add(intentActions);
+ return actionsList;
+ }
+
+ /**
+ * Create a list of Intent subjects
+ * @param src :Source Site Name
+ * @param dst :Destination Site Name
+ * @return :a list of Subjects
+ */
+ private List<Subjects> createSubjects(String src, String dst) {
+ List<Subjects> subjectList = new ArrayList<Subjects>();
+
+ EndPointGroup endpointGroupFrom = new EndPointGroupBuilder().setName(src).build();
+ org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup fromEPG =
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject
+ .EndPointGroupBuilder().setEndPointGroup(endpointGroupFrom).build();
+ Subjects subjects1 = new SubjectsBuilder().setOrder(FIRST_SUBJECT).setSubject(fromEPG).build();
+
+ EndPointGroup endpointGroupTo = new EndPointGroupBuilder().setName(dst).build();
+ org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject.EndPointGroup toEPG =
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.subjects.subject
+ .EndPointGroupBuilder().setEndPointGroup(endpointGroupTo).build();
+ Subjects subjects2 = new SubjectsBuilder().setOrder(SECOND_SUBJECT).setSubject(toEPG).build();
+
+ subjectList.add(subjects1);
+ subjectList.add(subjects2);
+ return subjectList;
+ }
+
+ /**
+ * Create a list of Intent constraints
+ * @param failOverType :Type of failover, fast-reroute or slow-reroute
+ * @return
+ */
+ private List<Constraints> createConstraints(String failOverType) {
+ List<Constraints> intentConstraints = new ArrayList<Constraints>();
+ if (failOverType==null) {
+ return intentConstraints;
+ }
+ short order = 1;
+ org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints.Constraints
+ protectionConstraint = null;
+ org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints.Constraints
+ failoverConstraint = null;
+ if (failOverType.equals(FAST_REROUTE)) {
+ protectionConstraint = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent
+ .constraints.constraints.ProtectionConstraintBuilder()
+ .setProtectionConstraint(new ProtectionConstraintBuilder().setIsProtected(true).build()).build();
+ failoverConstraint = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints
+ .constraints.FailoverConstraintBuilder()
+ .setFailoverConstraint(new FailoverConstraintBuilder().setFailoverSelector(FailoverType.FastReroute).build())
+ .build();
+ } else if (failOverType.equals(SLOW_REROUTE)) {
+ protectionConstraint = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent
+ .constraints.constraints.ProtectionConstraintBuilder()
+ .setProtectionConstraint(new ProtectionConstraintBuilder().setIsProtected(true).build()).build();
+ failoverConstraint = new org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intent.constraints
+ .constraints.FailoverConstraintBuilder()
+ .setFailoverConstraint(new FailoverConstraintBuilder().setFailoverSelector(FailoverType.SlowReroute).build())
+ .build();
+ }
+ Constraints constraint1 = new ConstraintsBuilder().setOrder(order).setConstraints(protectionConstraint).build();
+ Constraints constraint2 = new ConstraintsBuilder().setOrder(++order).setConstraints(failoverConstraint).build();
+ intentConstraints.add(constraint1);
+ intentConstraints.add(constraint2);
+ return intentConstraints;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.opendaylight.nic.mapping.api.IntentMappingService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+public class MappingServiceManager {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MappingServiceManager.class);
+ private IntentMappingService intentMappingService;
+ private String IP_PREFIX_PROPERTY = "ip_prefix";
+ private String SWITCH_PORT_ID_PROPERTY = "switch_port";
+ private String MPLS_LABEL_PROPERTY = "mpls_label";
+ private String NEXT_HOP_PROPERTY = "next_hop";
+
+ public MappingServiceManager(IntentMappingService intentMappingService) {
+ Preconditions.checkNotNull(intentMappingService);
+ this.intentMappingService = intentMappingService;
+ }
+
+ /**
+ * @param siteName
+ * Name of the member
+ * @param ipPrefix
+ * Ip prefix of the member
+ * @param switchPortId
+ * Switch ID and port ID (i.e. openflow:1:2)
+ * @param mplsLabel
+ * MPLS label, if needed
+ * @param nextHop
+ * Next hop in the route
+ */
+ public void add(final String siteName, final String ipPrefix, final String switchPortId, final Long mplsLabel,
+ final String nextHop) {
+ Preconditions.checkNotNull(siteName);
+ Preconditions.checkNotNull(ipPrefix);
+ Preconditions.checkNotNull(switchPortId);
+
+ Map<String, String> objs = new HashMap<>();
+ objs.put(IP_PREFIX_PROPERTY, ipPrefix);
+ objs.put(SWITCH_PORT_ID_PROPERTY, switchPortId);
+
+ if (mplsLabel != null)
+ objs.put(MPLS_LABEL_PROPERTY, String.valueOf(mplsLabel));
+ if (nextHop != null)
+ objs.put(NEXT_HOP_PROPERTY, nextHop);
+
+ intentMappingService.add(siteName, objs);
+ }
+
+ /**
+ * @param siteName
+ * Name of the member
+ * @return Map of parameters related to the member
+ */
+ public Map<String, String> get(String siteName) {
+ return intentMappingService.get(siteName);
+ }
+
+ /**
+ * @param siteName
+ * Name of the member
+ * @return Return true if transaction succeed, otherwise false
+ */
+ public boolean delete(String siteName) {
+ try {
+ // TODO: Implement delete() in mapping service
+ // By now, it's going to overwrite data for this key
+ intentMappingService.add(siteName, null);
+ return true;
+ } catch (Exception e) {
+ LOG.error("Error deleting from NIC's mapping service {}", e);
+ throw e;
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.nic.utils.MdsalUtils;
+import org.opendaylight.vpnservice.utils.IidFactory;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.MplsLabels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.labels.Label;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.labels.LabelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.labels.LabelKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.Endpoint;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MplsLabelManagerService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MplsLabelManagerService.class);
+ private static final Integer MAX_MPLS_LABEL = 524288;
+ private static InstanceIdentifier<Label> LABEL_IID = null;
+ public static final InstanceIdentifier<MplsLabels> MPLS_LABELS_IID = IidFactory.getMplsLabelsIid();
+ private final DataBroker dataBroker;
+ private final Random random = new Random();
+ private final MdsalUtils mdsal;
+
+ public MplsLabelManagerService(DataBroker dataBroker) {
+ this.dataBroker = dataBroker;
+ this.mdsal = new MdsalUtils(this.dataBroker);
+ }
+
+ /**
+ * Generate a unique Mpls Label
+ * Mpls label is of length 20 bits maximum
+ * @return :next unique Mpls label value
+ */
+ public Long getUniqueLabel(Endpoint endpoint) {
+ Long nextUniqueLabel = (long) random.nextInt(MAX_MPLS_LABEL);
+ while(checkIsLabelUsed(nextUniqueLabel)) {
+ nextUniqueLabel = (long) random.nextInt(MAX_MPLS_LABEL);
+ }
+ updateToLabelStore(nextUniqueLabel, endpoint, true);
+ return nextUniqueLabel;
+ }
+
+ /**
+ * Delete label from datastore
+ * @param endpoint :endpoint whose label needs to be deleted
+ */
+ public void deleteLabel(Endpoint endpoint) {
+ Map<Long, String> labelMap = getAllLabels();
+ for (Map.Entry<Long, String> labelEntry : labelMap.entrySet()) {
+ if(labelEntry.getValue().equalsIgnoreCase(endpoint.getSiteName())) {
+ updateToLabelStore(labelEntry.getKey(), endpoint, false);
+ }
+ }
+ }
+
+ /**
+ * Update the model for Labels with used Mpls label values
+ * @param label :mpls label allocated to an endpoint
+ * @param endpoint :endpoint to which mpls label is allocated to
+ * @param add :true if add label to datastore, false to delete label from datastore
+ */
+ private void updateToLabelStore(Long label, Endpoint endpoint, boolean add) {
+ LABEL_IID = IidFactory.getLabelIid(label);
+ Label mplsLabel = new LabelBuilder().
+ setKey(new LabelKey(label)).
+ setLabelId(label).
+ setSiteName(endpoint.getSiteName()).
+ setIpPrefix(endpoint.getIpPrefix()).
+ setSwitchPortId(endpoint.getSwitchPortId()).build();
+
+ if(add) {
+ mdsal.put(LogicalDatastoreType.OPERATIONAL, LABEL_IID, mplsLabel);
+ LOG.info("Add mpls label to operational datastore: {} for endpoint: {}", label, endpoint.getSiteName());
+ } else {
+ mdsal.delete(LogicalDatastoreType.OPERATIONAL, LABEL_IID);
+ LOG.info("Delete mpls label from operational datastore: {} for endpoint: {}", label, endpoint.getSiteName());
+ }
+ }
+
+ /**
+ * Check if label is already allocated to any endpoint
+ * @param nextUniqueLabel :value of mpls label
+ * @return :true is label is already used else false
+ */
+ private boolean checkIsLabelUsed(Long nextUniqueLabel) {
+ Map<Long, String> labelMap = getAllLabels();
+ if(labelMap.containsKey(nextUniqueLabel)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get a map of all the labels allocated to the endpoints
+ * @return :hashmap of labels as key, site names as value
+ */
+ private Map<Long, String> getAllLabels() {
+ Map<Long, String> labelMap = new HashMap<>();
+ MplsLabels mplsLabels = mdsal.read(LogicalDatastoreType.OPERATIONAL, MPLS_LABELS_IID);
+ if(mplsLabels != null) {
+ for (Label label : mplsLabels.getLabel()) {
+ labelMap.put(label.getLabelId(), label.getSiteName());
+ }
+ }
+ return labelMap;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.impl;
+
+import java.util.concurrent.Future;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+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.nic.mapping.api.IntentMappingService;
+import org.opendaylight.nic.utils.MdsalUtils;
+import org.opendaylight.vpnservice.utils.IidFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.AddVpnEndpointInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.FailoverType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.MplsLabels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.MplsLabelsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.RemoveVpnEndpointInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.RemoveVpnInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.VpnintentService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.Vpns;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.VpnsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.EndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.EndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpns.VpnIntents;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpns.VpnIntentsKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
+public class VpnintentProvider implements VpnintentService, BindingAwareProvider, AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(VpnintentProvider.class);
+ public static final InstanceIdentifier<MplsLabels> LABELS_IID = IidFactory.getMplsLabelsIid();
+ public static final InstanceIdentifier<Vpns> VPN_IID = IidFactory.getVpnsIid();
+ public static final InstanceIdentifier<VpnIntents> VPN_INTENT_IID = IidFactory.getVpnIntentIid();
+ public static final InstanceIdentifier<Endpoint> ENDPOINT_IID = IidFactory.getEndpointIid();
+
+ private DataBroker dataBroker;
+ private IntentMappingService intentMappingService;
+ private BindingAwareBroker.RpcRegistration<VpnintentService> rpcRegistration = null;
+ private MdsalUtils mdsal;
+
+ @Override
+ public void onSessionInitiated(ProviderContext session) {
+ LOG.info("VpnintentProvider Session Initiated");
+ dataBroker = session.getSALService(DataBroker.class);
+ rpcRegistration = session.addRpcImplementation(VpnintentService.class, this);
+ this.mdsal = new MdsalUtils(this.dataBroker);
+
+ // Load IntentMappingService Reference
+ loadIntentMappingServiceReference();
+
+ Vpns vpns = new VpnsBuilder().build();
+ MplsLabels labels = new MplsLabelsBuilder().build();
+
+ // Initialize MD-SAL data store for vpn-intents and mpls-labels
+ initDatastore(LogicalDatastoreType.CONFIGURATION, VPN_IID, vpns);
+ initDatastore(LogicalDatastoreType.OPERATIONAL, LABELS_IID, labels);
+ }
+
+ @Override
+ public void close() throws Exception {
+ LOG.info("VpnintentProvider Closed");
+ }
+
+ private <T extends DataObject> void initDatastore(LogicalDatastoreType store, InstanceIdentifier<T> iid, T object) {
+ // Put data to MD-SAL data store
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+ transaction.put(store, iid, object);
+
+ // Perform the tx.submit asynchronously
+ Futures.addCallback(transaction.submit(), new FutureCallback<Void>() {
+ @Override
+ public void onSuccess(final Void result) {
+ LOG.info("initDatastore for VPN-Intents: transaction succeeded");
+ }
+
+ @Override
+ public void onFailure(final Throwable throwable) {
+ LOG.error("initDatastore for VPN-Intents: transaction failed");
+ }
+ });
+ LOG.info("initDatastore: data populated: {}, {}, {}", store, iid, object);
+ }
+
+ @Override
+ public Future<RpcResult<Void>> removeVpn(RemoveVpnInput input) {
+ InstanceIdentifier<VpnIntents> vpnIdentifier = InstanceIdentifier.builder(Vpns.class)
+ .child(VpnIntents.class, new VpnIntentsKey(input.getVpnName())).build();
+ MappingServiceManager msManager = new MappingServiceManager(intentMappingService);
+ MplsLabelManagerService mplsManager = new MplsLabelManagerService(dataBroker);
+
+ VpnIntents vpn = getVpn(input.getVpnName());
+
+ if (vpn.getEndpoint() != null && vpn.getEndpoint().size() > 0) {
+ for (Endpoint endpoint : vpn.getEndpoint()) {
+ // Release MPLS label
+ mplsManager.deleteLabel(endpoint);
+
+ // Remove all intents related to this endpoint
+ IntentServiceManager intentManager = new IntentServiceManager(dataBroker);
+ intentManager.removeIntentsByEndpoint(endpoint.getSiteName());
+
+ // Remove info from Mapping Service
+ msManager.delete(endpoint.getSiteName());
+ }
+ }
+
+ mdsal.delete(LogicalDatastoreType.CONFIGURATION, vpnIdentifier);
+ LOG.info("Deleted VPN {}", input.getVpnName());
+ return Futures.immediateFuture(RpcResultBuilder.<Void> success().build());
+ }
+
+ @Override
+ public Future<RpcResult<Void>> addVpnEndpoint(AddVpnEndpointInput input) {
+ Endpoint currentEndpoint = new EndpointBuilder().setIpPrefix(input.getIpPrefix())
+ .setSiteName(input.getSiteName()).setSwitchPortId(input.getSwitchPortId())
+ .setKey(new EndpointKey(input.getSiteName())).build();
+ VpnIntents vpn = getVpn(input.getVpnName());
+ String failOverType = null;
+ if (vpn.isPathProtection() && vpn.getFailoverType()!= null) {
+ if (vpn.getFailoverType().equals(FailoverType.FastReroute)) {
+ failOverType = IntentServiceManager.FAST_REROUTE;
+ } else if(vpn.getFailoverType().equals(FailoverType.SlowReroute)) {
+ failOverType = IntentServiceManager.SLOW_REROUTE;
+ }
+ }
+
+ MplsLabelManagerService mplsManager = new MplsLabelManagerService(dataBroker);
+
+ // Get unique MPLS label
+ Long mplsLabel = mplsManager.getUniqueLabel(currentEndpoint);
+
+ // Add info into Mapping Service
+ MappingServiceManager msManager = new MappingServiceManager(intentMappingService);
+ msManager.add(currentEndpoint.getSiteName(), extractIP(currentEndpoint.getIpPrefix()),
+ currentEndpoint.getSwitchPortId(), mplsLabel, null);
+
+ if (vpn.getEndpoint() != null && vpn.getEndpoint().size() > 0) {
+ IntentServiceManager intentManager = new IntentServiceManager(dataBroker);
+
+ for (Endpoint member : vpn.getEndpoint()) {
+ // Create mesh of Intents
+ intentManager.addIntent(member.getSiteName(), currentEndpoint.getSiteName(),
+ IntentServiceManager.ACTION_ALLOW, failOverType);
+ intentManager.addIntent(currentEndpoint.getSiteName(), member.getSiteName(),
+ IntentServiceManager.ACTION_ALLOW, failOverType);
+ }
+ }
+ // Associate endpoint with VPN
+ addEndpointToVpn(vpn, currentEndpoint);
+
+ return Futures.immediateFuture(RpcResultBuilder.<Void> success().build());
+ }
+
+ /**
+ * @param IpPrefix
+ * object
+ * @return String representation of IP prefix
+ */
+ private String extractIP(IpPrefix ipPrefix) {
+ String ip = null;
+ if (ipPrefix.getIpv4Prefix() != null) {
+ ip = ipPrefix.getIpv4Prefix().getValue();
+ } else if (ipPrefix.getIpv6Prefix() != null) {
+ ip = ipPrefix.getIpv6Prefix().getValue();
+ }
+ return ip;
+ }
+
+ /**
+ * @param vpnName
+ * VPN name
+ * @return VPN instance
+ */
+ private VpnIntents getVpn(String vpnName) {
+ InstanceIdentifier<VpnIntents> identifier = InstanceIdentifier.builder(Vpns.class)
+ .child(VpnIntents.class, new VpnIntentsKey(vpnName)).build();
+
+ VpnIntents vpnIntents = mdsal.read(LogicalDatastoreType.CONFIGURATION, identifier);
+ Preconditions.checkNotNull(vpnIntents);
+ return vpnIntents;
+ }
+
+ @Override
+ public Future<RpcResult<Void>> removeVpnEndpoint(RemoveVpnEndpointInput input) {
+ Endpoint endpoint = getEndpoint(input.getVpnName(), input.getSiteName());
+
+ // Release MPLS label
+ MplsLabelManagerService mplsManager = new MplsLabelManagerService(dataBroker);
+ mplsManager.deleteLabel(endpoint);
+
+ // Remove all intents related to this endpoint
+ IntentServiceManager intentManager = new IntentServiceManager(dataBroker);
+ intentManager.removeIntentsByEndpoint(input.getSiteName());
+
+ // Remove endpoint from VPN
+ removeEndpointFromVpn(input.getVpnName(), input.getSiteName());
+
+ return Futures.immediateFuture(RpcResultBuilder.<Void> success().build());
+ }
+
+ /**
+ * @param siteName
+ * Site name of the VPN member
+ * @return VPN member (Endpoint)
+ */
+ private Endpoint getEndpoint(String vpnName, String siteName) {
+ InstanceIdentifier<Endpoint> endpointID = InstanceIdentifier.builder(Vpns.class)
+ .child(VpnIntents.class, new VpnIntentsKey(vpnName)).child(Endpoint.class, new EndpointKey(siteName))
+ .build();
+
+ return mdsal.read(LogicalDatastoreType.CONFIGURATION, endpointID);
+ }
+
+ /**
+ * @param vpnName
+ * VPN name
+ * @param siteName
+ * Site name
+ */
+ private void removeEndpointFromVpn(String vpnName, String siteName) {
+ InstanceIdentifier<Endpoint> identifier = InstanceIdentifier.builder(Vpns.class)
+ .child(VpnIntents.class, new VpnIntentsKey(vpnName)).child(Endpoint.class, new EndpointKey(siteName))
+ .build();
+
+ mdsal.delete(LogicalDatastoreType.CONFIGURATION, identifier);
+ LOG.info("Deleted VPN member : {} from VPN: {}", siteName, vpnName);
+ }
+
+ /**
+ * @param vpn
+ * VPN
+ * @param vpnMember
+ * VPN member (endpoint)
+ */
+ private void addEndpointToVpn(VpnIntents vpn, Endpoint vpnMember) {
+ InstanceIdentifier<Endpoint> identifier = InstanceIdentifier.builder(Vpns.class)
+ .child(VpnIntents.class, vpn.getKey())
+ .child(Endpoint.class, vpnMember.getKey()).build();
+
+ mdsal.put(LogicalDatastoreType.CONFIGURATION, identifier, vpnMember);
+ LOG.info("Added VPN member : {} to VPN: {}", vpnMember.getSiteName(), vpn.getVpnName());
+ }
+
+ /**
+ * Load IntentMappingService reference
+ */
+ private void loadIntentMappingServiceReference() {
+ ServiceReference<?> serviceReference = getBundleCtx().getServiceReference(IntentMappingService.class);
+ intentMappingService = (IntentMappingService) getBundleCtx().getService(serviceReference);
+ }
+
+ private BundleContext getBundleCtx() {
+ return FrameworkUtil.getBundle(this.getClass()).getBundleContext();
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.utils;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.Intents;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.MplsLabels;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.Vpns;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.labels.Label;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.labels.LabelKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpn.intent.Endpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.rev150105.vpns.VpnIntents;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class IidFactory {
+
+ public static InstanceIdentifier<MplsLabels> getMplsLabelsIid() {
+ return InstanceIdentifier.builder(MplsLabels.class).build();
+ }
+
+ public static InstanceIdentifier<Label> getLabelIid(Long label) {
+ return InstanceIdentifier.create(MplsLabels.class).child(Label.class, new LabelKey(label));
+ }
+
+ public static InstanceIdentifier<Intents> getIntentsIid() {
+ return InstanceIdentifier.builder(Intents.class).build();
+ }
+
+ public static InstanceIdentifier<Vpns> getVpnsIid() {
+ return InstanceIdentifier.builder(Vpns.class).build();
+ }
+
+ public static InstanceIdentifier<VpnIntents> getVpnIntentIid() {
+ return InstanceIdentifier.builder(Vpns.class).child(VpnIntents.class).build();
+ }
+
+ public static InstanceIdentifier<Endpoint> getEndpointIid() {
+ return InstanceIdentifier.builder(Vpns.class).child(VpnIntents.class).child(Endpoint.class).build();
+ }
+}
--- /dev/null
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.impl.rev141210;
+
+import org.opendaylight.vpnservice.impl.VpnintentProvider;
+
+public class VpnintentImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.impl.rev141210.AbstractVpnintentImplModule {
+ public VpnintentImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public VpnintentImplModule(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.vpnintent.impl.rev141210.VpnintentImplModule 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() {
+ VpnintentProvider provider = new VpnintentProvider();
+ getBrokerDependency().registerProvider(provider);
+ return provider;
+ }
+
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: vpnintent-impl yang module local name: vpnintent-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Wed Dec 16 22:44:32 EST 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.vpnintent.impl.rev141210;
+public class VpnintentImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnintent.impl.rev141210.AbstractVpnintentImplModuleFactory {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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
+ */
+module vpnintent-impl {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:vpnintent:impl";
+ prefix "vpnintent-impl";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
+
+ description
+ "Service definition for vpnintent project";
+
+ revision "2014-12-10" {
+ description
+ "Initial revision";
+ }
+
+ identity vpnintent-impl {
+ base config:module-type;
+ config:java-name-prefix VpnintentImpl;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case vpnintent-impl {
+ when "/config:modules/config:module/config:type = 'vpnintent-impl'";
+ container broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-broker-osgi-registry;
+ }
+ }
+ }
+ container rpc-registry {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding:binding-rpc-registry;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.impl;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.nic.utils.MdsalUtils;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.Intents;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.IntentsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.Intent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.rev150122.intents.IntentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.intent.types.rev150122.Uuid;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.api.support.membermodification.MemberModifier;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+@PrepareForTest({IntentServiceManager.class})
+@RunWith(PowerMockRunner.class)
+public class IntentServiceManagerTest {
+
+ private static final String SRC_SITE_NAME = "site a";
+ private static final String DST_SITE_NAME = "site b";
+ private static final String INTENT_ALLOW_ACTION = "ALLOW";
+ private IntentServiceManager intentServiceManager;
+ @Mock private MdsalUtils mdsal;
+
+ @Before
+ public void setUp() throws Exception {
+ intentServiceManager = mock(IntentServiceManager.class, Mockito.CALLS_REAL_METHODS);
+ MemberModifier.field(IntentServiceManager.class, "mdsal").set(intentServiceManager, mdsal);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testAddIntent() throws Exception {
+ IntentBuilder intentBldr = mock(IntentBuilder.class);
+ PowerMockito.whenNew(IntentBuilder.class).withNoArguments().thenReturn(intentBldr);
+ when(intentBldr.setId(any(Uuid.class))).thenReturn(intentBldr);
+ when(intentBldr.setSubjects(any(List.class))).thenReturn(intentBldr);
+ when(intentBldr.setActions(any(List.class))).thenReturn(intentBldr);
+ when(intentBldr.setConstraints(any(List.class))).thenReturn(intentBldr);
+ when(intentBldr.build()).thenReturn(mock(Intent.class));
+
+ Intents currentIntents = mock(Intents.class);
+ PowerMockito.when(mdsal.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class))).thenReturn(currentIntents);
+ IntentsBuilder intentsBldr = mock(IntentsBuilder.class);
+ PowerMockito.whenNew(IntentsBuilder.class).withNoArguments().thenReturn(intentsBldr);
+ when(intentsBldr.setIntent(any(List.class))).thenReturn(intentsBldr);
+ PowerMockito.when(mdsal.put(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(Intents.class))).thenReturn(true);
+
+ intentServiceManager.addIntent(SRC_SITE_NAME, DST_SITE_NAME, INTENT_ALLOW_ACTION, "fast-reroute");
+ verify(intentBldr).setId(any(Uuid.class));
+ verify(mdsal).read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class));
+ verify(mdsal).put(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(Intents.class));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testRemoveIntents() {
+ Uuid id = mock(Uuid.class);
+ when(mdsal.delete(any(LogicalDatastoreType.class), any(InstanceIdentifier.class))).thenReturn(true);
+
+ intentServiceManager.removeIntent(id);
+ verify(mdsal).delete(any(LogicalDatastoreType.class), any(InstanceIdentifier.class));
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+import org.opendaylight.nic.mapping.api.IntentMappingService;
+
+public class MappingServiceManagerTests {
+
+ @Test
+ public void addInfo() {
+ // Arrange
+ String siteName = "UoR";
+ String ipPrefix = "16.101.233.2/8";
+ String switchPortId = "openflow:1:3";
+ long mplsLabel = 10L;
+ String nextHop = "16.101.233.1/8";
+
+ Map<String, String> map = new HashMap<>();
+ map.put("ip_prefix", ipPrefix);
+ map.put("switch_port", switchPortId);
+ map.put("mpls_label", String.valueOf(mplsLabel));
+ map.put("next_hop", nextHop);
+
+ IntentMappingService mapSvc = mock(IntentMappingService.class);
+ when(mapSvc.get(any(String.class))).thenReturn(map);
+
+ MappingServiceManager manager = new MappingServiceManager(mapSvc);
+
+ // Act
+ manager.add(siteName, ipPrefix, switchPortId, mplsLabel, nextHop);
+
+ Map<String, String> returnedObjs = manager.get(siteName);
+
+ // Assert
+ assertEquals(ipPrefix, returnedObjs.get("ip_prefix"));
+ assertEquals(switchPortId, returnedObjs.get("switch_port"));
+ assertEquals(mplsLabel, Long.parseLong(returnedObjs.get("mpls_label")));
+ assertEquals(nextHop, returnedObjs.get("next_hop"));
+ }
+
+ @Test
+ public void removeInfo() {
+ // Arrange
+ String siteName = "UoR";
+ String ipPrefix = "16.101.233.2/8";
+ String switchPortId = "openflow:1:3";
+
+ Map<String, String> map = new HashMap<>();
+ map.put("ip_prefix", ipPrefix);
+ map.put("switch_port", switchPortId);
+
+ IntentMappingService mapSvc = mock(IntentMappingService.class);
+
+ MappingServiceManager manager = new MappingServiceManager(mapSvc);
+
+ // Add first to delete next
+ manager.add(siteName, ipPrefix, switchPortId, null, null);
+
+ // Act
+ boolean result = manager.delete(siteName);
+
+ // Assert
+ assertTrue(result);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Inocybe Technologies 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.impl;
+
+import static org.mockito.Mockito.mock;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+
+public class VpnintentProviderTest {
+ @Ignore
+ @Test
+ public void testOnSessionInitiated() {
+ VpnintentProvider provider = new VpnintentProvider();
+
+ // ensure no exceptions
+ // currently this method is empty
+ provider.onSessionInitiated(mock(BindingAwareBroker.ProviderContext.class));
+ }
+
+ @Ignore
+ @Test
+ public void testClose() throws Exception {
+ VpnintentProvider provider = new VpnintentProvider();
+
+ // ensure no exceptions
+ // currently this method is empty
+ provider.close();
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2016 Inocybe Technologies 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-lite</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>vpnintent-aggregator</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <name>vpnintent</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>api</module>
+ <module>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>
+
--- /dev/null
+{
+ "id": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "name": "VPN Intents",
+ "description": "Apply protection and failover-type constraints to VpnService and NIC. When protections is set to true, and failover type is either soft-reroute or hard-reroute then the end-to-end connectivity is self-healing in case of link/node failure. VpnService shall create Intent object with constraints embedded in it (constraints are set by users) and NIC renders flows according based on the constraints.\n\nDisjoint Path Calculation using Suurballe Algorithm when soft-reroute constraint is applied to NIC, two disjoint paths are calculated. When one of the paths is non-usable due to a link/node failure the other disjoint path is automatically invoked to push required flows for all the intents that get affection by the failed path.\n\nDelete flows from the switch when an intent is removed: NIC did not support deleting flows from the nodes when an intent was removed, this was also fixed.",
+ "order": [],
+ "folders": [
+ {
+ "id": "d424223b-11b7-b00d-3875-70b5fb4e6e85",
+ "name": "Add Members to VPN",
+ "description": "",
+ "order": [
+ "bfcc70b5-208a-d64e-7277-f4174b5f9ff9",
+ "45328601-ed77-b7ff-0ae6-c5734c69c170",
+ "84f7e114-532c-02d4-45fa-6e335f2a7e5d",
+ "6421391f-20de-e31b-00a4-5cf36297c074"
+ ],
+ "owner": "255113",
+ "collectionId": "6f9c9d85-2bda-9f02-eaec-a5269af5c0b5"
+ },
+ {
+ "id": "2049f3c6-ebf5-a456-61de-ee9abd1811f4",
+ "name": "Create VPN",
+ "description": "",
+ "order": [
+ "e5f75d2a-c350-e601-5029-e6e5ea736eef",
+ "91d91020-d5e0-2aaf-6c09-ed9cdec077de",
+ "72ac6ee2-90a8-36b1-0dda-9eb886df197c"
+ ],
+ "owner": "255113",
+ "collectionId": "6f9c9d85-2bda-9f02-eaec-a5269af5c0b5"
+ },
+ {
+ "id": "a2deb454-a0e6-3870-0c64-ba7fdffaccba",
+ "name": "MPLS Label Management",
+ "description": "Includes a set of GET operations to access the labels assigned to each member",
+ "order": [
+ "e7ba99ee-7804-d411-e652-9d932687a35c"
+ ],
+ "owner": "255113",
+ "collectionId": "efd3dae9-0818-468a-0d86-86fcec008d22"
+ },
+ {
+ "id": "118a7d9f-7925-4e75-d59a-f9c151b1c4c4",
+ "name": "Network Intent Composition Operations",
+ "description": "GET operations to check the state of Intents",
+ "order": [
+ "109d1ae7-bdd4-907e-be5d-61b6f493640b"
+ ],
+ "owner": "255113",
+ "collectionId": "748af960-874f-028d-cbd0-74134a3c6db7"
+ },
+ {
+ "id": "3ab1d430-5cc5-f506-0619-b827cc6f645b",
+ "name": "Remove Member from VPN",
+ "description": "",
+ "order": [
+ "d3250d1d-ca8d-9a31-dec7-4ded8720e530",
+ "42034ad0-1789-a773-6be3-9b9b5c4881bf",
+ "13757df8-f5ea-c933-a991-b9a8e4d60b07",
+ "0063438d-94b1-5ca3-88f2-1d789f3d2251"
+ ],
+ "owner": "255113",
+ "collectionId": "6f9c9d85-2bda-9f02-eaec-a5269af5c0b5"
+ },
+ {
+ "id": "3958cf6c-b82e-f0d4-a5c3-ce0bb85464c7",
+ "name": "Remove VPN",
+ "description": "",
+ "order": [
+ "63050e81-9cac-5de5-2180-7ed5c6bd361a",
+ "b0ac20bf-7cad-e958-761c-a83a456afdd4"
+ ],
+ "owner": "255113"
+ }
+ ],
+ "timestamp": 1450878947771,
+ "owner": "255113",
+ "remoteLink": "",
+ "public": false,
+ "requests": [
+ {
+ "id": "0063438d-94b1-5ca3-88f2-1d789f3d2251",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operations/vpnintent:remove-vpn-endpoint",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741595237,
+ "name": "Remove Member 4 (site 4) from unprotected VPN",
+ "description": "Remove a Member from a VPN\n\nParameters description\nsite-name: Name of the member\nvpn-name: The VPN from which the member should be deleted",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"input\": {\n \"vpn-name\": \"VPN unprotected\",\n \"site-name\": \"site 4\"\n }\n}"
+ },
+ {
+ "id": "109d1ae7-bdd4-907e-be5d-61b6f493640b",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/config/intent:intents/",
+ "pathVariables": {},
+ "preRequestScript": "",
+ "method": "GET",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "data": [],
+ "dataMode": "params",
+ "name": "GET intents",
+ "description": "Gets a list of intents added",
+ "descriptionFormat": "html",
+ "time": 1450721033712,
+ "version": 2,
+ "responses": [],
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "folder": "118a7d9f-7925-4e75-d59a-f9c151b1c4c4"
+ },
+ {
+ "id": "13757df8-f5ea-c933-a991-b9a8e4d60b07",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operations/vpnintent:remove-vpn-endpoint",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741569695,
+ "name": "Remove Member 3 (site 3) from unprotected VPN",
+ "description": "Remove a Member from a VPN\n\nParameters description\nsite-name: Name of the member\nvpn-name: The VPN from which the member should be deleted",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"input\": {\n \"vpn-name\": \"VPN unprotected\",\n \"site-name\": \"site 3\"\n }\n}"
+ },
+ {
+ "id": "42034ad0-1789-a773-6be3-9b9b5c4881bf",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operations/vpnintent:remove-vpn-endpoint",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741544712,
+ "name": "Remove Member 2 (site 2) from protected VPN",
+ "description": "Remove a Member from a VPN\n\nParameters description\nsite-name: Name of the member\nvpn-name: The VPN from which the member should be deleted",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"input\": {\n \"vpn-name\": \"VPN protected\",\n \"site-name\": \"site 2\"\n }\n}"
+ },
+ {
+ "id": "45328601-ed77-b7ff-0ae6-c5734c69c170",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operations/vpnintent:add-vpn-endpoint",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741386479,
+ "name": "Add Member 2 (site 2) to protected VPN",
+ "description": "Add a Member to a protected VPN\n\nParameters description\nsite-name: Name of the member\nip-prefix: The IP Prefix associated with the Site-Name\nswitch-port-id: The PE switch id:port to which the site is connected to\nvpn-name: The VPN to which the member should belong to",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"input\": {\n \"vpn-name\": \"VPN protected\",\n \"site-name\": \"site 2\",\n \"ip-prefix\": \"10.0.0.2/32\",\n \"switch-port-id\": \"openflow:2:1\"\n }\n}"
+ },
+ {
+ "id": "63050e81-9cac-5de5-2180-7ed5c6bd361a",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operations/vpnintent:remove-vpn",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741509183,
+ "name": "Remove protected VPN",
+ "description": "Delete a VPN\n\nParameters description\nvpn-name: The VPN that needs to be deleted",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"input\": {\n \"vpn-name\": \"VPN protected\"\n }\n}"
+ },
+ {
+ "id": "6421391f-20de-e31b-00a4-5cf36297c074",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operations/vpnintent:add-vpn-endpoint",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741358417,
+ "name": "Add Member 4 (site 4) to unprotected VPN",
+ "description": "Add a Member to an unprotected VPN\n\nParameters description\nsite-name: Name of the member\nip-prefix: The IP Prefix associated with the Site-Name\nswitch-port-id: The PE switch id:port to which the site is connected to\nvpn-name: The VPN to which the member should belong to",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"input\": {\n \"vpn-name\": \"VPN unprotected\",\n \"site-name\": \"site 4\",\n \"ip-prefix\": \"10.0.0.4/32\",\n \"switch-port-id\": \"openflow:4:1\"\n }\n}"
+ },
+ {
+ "id": "72ac6ee2-90a8-36b1-0dda-9eb886df197c",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/config/vpnintent:vpns/",
+ "pathVariables": {},
+ "preRequestScript": "",
+ "method": "GET",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "data": [],
+ "dataMode": "params",
+ "name": "GET VPNs",
+ "description": "Gets a list of all the VPNs along with the list of members that belong to these VPNs",
+ "descriptionFormat": "html",
+ "time": 1450716801343,
+ "version": 2,
+ "responses": [],
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "folder": "2049f3c6-ebf5-a456-61de-ee9abd1811f4"
+ },
+ {
+ "id": "84f7e114-532c-02d4-45fa-6e335f2a7e5d",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operations/vpnintent:add-vpn-endpoint",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741323406,
+ "name": "Add Member 3 (site 3) to unprotected VPN",
+ "description": "Add a Member to an unprotected VPN\n\nParameters description\nsite-name: Name of the member\nip-prefix: The IP Prefix associated with the Site-Name\nswitch-port-id: The PE switch id:port to which the site is connected to\nvpn-name: The VPN to which the member should belong to",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"input\": {\n \"vpn-name\": \"VPN unprotected\",\n \"site-name\": \"site 3\",\n \"ip-prefix\": \"10.0.0.1/32\",\n \"switch-port-id\": \"openflow:3:1\"\n }\n}"
+ },
+ {
+ "id": "91d91020-d5e0-2aaf-6c09-ed9cdec077de",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/config/vpnintent:vpns/",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741250149,
+ "name": "Create an unprotected VPN",
+ "description": "Create a protected VPN by pushing to config data tree to the Vpn-intents Yang model\n\nParameters description\nvpn-name: The name of the VPN that you intend to create\nprotection: True if path protection is needed\nfailover-type: Type of failover mechanism\n - slow-reroute\n - fast-reroute",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"vpn-intents\": [\n {\n \"vpn-name\": \"VPN unprotected\",\n \"path-protection\": \"false\",\n \"failover-type\": \"slow-reroute\"\n }\n ]\n}"
+ },
+ {
+ "id": "b0ac20bf-7cad-e958-761c-a83a456afdd4",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operations/vpnintent:remove-vpn",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741501187,
+ "name": "Remove unprotected VPN",
+ "description": "Delete a VPN\n\nParameters description\nvpn-name: The VPN that needs to be deleted",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"input\": {\n \"vpn-name\": \"VPN unprotected\"\n }\n}"
+ },
+ {
+ "id": "bfcc70b5-208a-d64e-7277-f4174b5f9ff9",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operations/vpnintent:add-vpn-endpoint",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741369995,
+ "name": "Add Member 1 (site 1) to protected VPN",
+ "description": "Add a Member to a protected VPN\n\nParameters description\nsite-name: Name of the member\nip-prefix: The IP Prefix associated with the Site-Name\nswitch-port-id: The PE switch id:port to which the site is connected to\nvpn-name: The VPN to which the member should belong to",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"input\": {\n \"vpn-name\": \"VPN protected\",\n \"site-name\": \"site 1\",\n \"ip-prefix\": \"10.0.0.1/32\",\n \"switch-port-id\": \"openflow:1:1\"\n }\n}"
+ },
+ {
+ "id": "d3250d1d-ca8d-9a31-dec7-4ded8720e530",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operations/vpnintent:remove-vpn-endpoint",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741522615,
+ "name": "Remove Member 1 (site 1) from protected VPN",
+ "description": "Remove a Member from a VPN\n\nParameters description\nsite-name: Name of the member\nvpn-name: The VPN from which the member should be deleted",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"input\": {\n \"vpn-name\": \"VPN protected\",\n \"site-name\": \"site 1\"\n }\n}"
+ },
+ {
+ "id": "e5f75d2a-c350-e601-5029-e6e5ea736eef",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/config/vpnintent:vpns/",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "POST",
+ "data": [],
+ "dataMode": "raw",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452741238916,
+ "name": "Create a protected VPN",
+ "description": "Create a protected VPN by pushing to config data tree to the Vpn-intents Yang model\n\nParameters description\nvpn-name: The name of the VPN that you intend to create\nprotection: True if path protection is needed\nfailover-type: Type of failover mechanism\n - slow-reroute\n - fast-reroute",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "rawModeData": "{\n \"vpn-intents\": [\n {\n \"vpn-name\": \"VPN protected\",\n \"path-protection\": \"true\",\n \"failover-type\": \"slow-reroute\"\n }\n ]\n}"
+ },
+ {
+ "id": "e7ba99ee-7804-d411-e652-9d932687a35c",
+ "headers": "Authorization: Basic YWRtaW46YWRtaW4=\nAccept: application/xml\nContent-Type: application/json\n",
+ "url": "http://localhost:8181/restconf/operational/vpnintent:mpls-labels",
+ "preRequestScript": "",
+ "pathVariables": {},
+ "method": "GET",
+ "data": [],
+ "dataMode": "params",
+ "version": 2,
+ "tests": "",
+ "currentHelper": "normal",
+ "helperAttributes": {},
+ "time": 1452282516268,
+ "name": "GET all unique MPLS Labels",
+ "description": "Gets a list of unique labels assigned to every Member in the VPN",
+ "collectionId": "6250512e-90d0-2fb5-259d-2496c6cd8426",
+ "responses": [],
+ "folder": "a2deb454-a0e6-3870-0c64-ba7fdffaccba"
+ }
+ ]
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>vpnmanager</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <name>vpnmanager</name>
+ <packaging>pom</packaging>
+ <modelVersion>4.0.0</modelVersion>
+ <prerequisites>
+ <maven>3.1.1</maven>
+ </prerequisites>
+ <modules>
+ <module>vpnmanager-api</module>
+ <module>vpnmanager-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>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>vpnmanager-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.yangtools</groupId>
+ <artifactId>yang-common</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.vpnservice</groupId>
+ <artifactId>model-bgp</artifactId>
+ <version>${model.bgp.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>fibmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.vpnmanager.api;
+
+import java.math.BigInteger;
+
+import java.util.Collection;
+import org.opendaylight.fibmanager.api.IFibManager;
+
+public interface IVpnManager {
+ void setFibService(IFibManager fibManager);
+ void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label);
+ void delExtraRoute(String destination, String rd, String routerID);
+}
--- /dev/null
+module l3vpn {
+ namespace "urn:huawei:params:xml:ns:yang:l3vpn";
+// replace with IANA namespace when assigned
+ prefix "l3vpn";
+
+ import bgp {
+ prefix bgp;
+ //draft-zhdankin-netmod-bgp-cfg
+ }
+ import ietf-interfaces {
+ prefix if;
+ //rfc7223-YANG Interface Management
+ }
+
+ import ietf-inet-types {
+ prefix inet;
+ revision-date "2010-09-24";
+ //RFC6991
+ }
+
+ import ietf-yang-types {
+ prefix yang;
+ //RFC6991
+ }
+
+ description
+ "This YANG module defines the generic configuration data for L3VPN service.
+
+ Terms and Acronyms
+
+ BGP (bgp): Border Gateway Protocol
+ IPv4 (ipv4):Internet Protocol Version 4
+ IPv6 (ipv6): Internet Protocol Version 6
+
+ ";
+
+ revision 2014-08-15 {
+ description
+ "Initial revision.";
+ reference "RFC4271, RFC4364, RFC4760";
+ }
+
+ grouping augment-bgp-af-vpn-config {
+ description
+ "A set of configuration parameters that is applicable to both BGP-VPNv4
+ and BGP-VPNv6 address family.";
+
+ leaf apply-label-per-nexthop {
+ description
+ "The apply-label per-nexthop command enables the ASBR to allocate
+ labels for IPv4 VPN routes or IPv6 VPN routes based on the next hop.";
+
+
+
+ config "true";
+ type boolean;
+ default "false";
+ }
+
+ leaf upeEnable {
+ description
+ "Specify peer as UPE.";
+
+ config "true";
+ type boolean;
+ default "false";
+ }
+
+ }
+
+
+ grouping bgp-af-vpn-instance-config {
+
+ container router-id {
+ description
+ "The router-id command configures router ID for BGP VPN instance IPv4
+ or IPv6 address family.
+ By default, no router ID is configured for BGP VPN instance IPv4 or
+ IPv6 address family, and the BGP router ID is used as the router ID.";
+
+ leaf enable {
+ type boolean;
+ }
+
+ choice config-type {
+ case static {
+ leaf ip-address {
+ description
+ "Specifies the router ID of a BGP VPN instance IPv4 address
+ family. The router ID is expressed in the IPv4 address format.
+ ";
+
+ config "true";
+ type inet:ip-address;
+ }
+ }
+ case auto-select {
+ leaf enable-auto-select {
+ description
+ "Configures automatic route ID selection for the current BGP VPN
+ instance address family.";
+
+
+ config "true";
+ type boolean;
+ }
+ }
+ }
+ }
+
+ leaf auto-frr {
+ description
+ "The auto-frr command enables BGP Auto FRR.";
+
+ config "true";
+ type boolean;
+ default "false";
+ }
+
+ container bgpPeers {
+ list bgpPeer {
+ key "peerAddr";
+ max-elements "unbounded";
+ min-elements "0";
+ description
+ "BGP Peer configure class";
+
+ leaf peerAddr {
+ description
+ "The nerighbor address";
+ config "true";
+ type inet:ip-address;
+ mandatory true;
+ }
+
+ leaf groupName {
+ description "peerGroupName";
+ config "true";
+ type string {
+ length "1..47";
+ }
+ }
+ leaf remoteAs {
+ description "Specifies the AS number of the peer.";
+ config "true";
+ type string {
+ length "1..11";
+ }
+ }
+
+ leaf description {
+
+ description
+ "specifies the description. The description is a string of letters
+ or figures. The value ranges from 1 to 80 characters without
+ spaces.";
+ config "true";
+ type string {
+ length "1..80";
+ pattern "([^?]*)";
+ }
+ }
+
+ leaf soo {
+ description
+ "The peer soo command configures the Site of Origin (SoO)
+ attribute for an EBGP peer in a BGP VPN instance. Format is ASN:nn
+ or IP-address:nn.";
+
+ config "true";
+ type string {
+ length "3..21";
+ }
+ }
+
+ leaf substituteAsEnable {
+ description
+ "Using the peer substitute-as command, you can substitute the AS
+ number of the specified peer in the as-path with the local AS
+ number.";
+
+ config "true";
+ type boolean;
+ default "false";
+ }
+
+ }
+ }
+
+ }
+
+ grouping vpn-af-config {
+ description
+ "A set of configuration parameters that is applicable to both IPv4 and
+ IPv6 address family for a VPN instance .";
+
+ leaf route-distinguisher {
+ description
+ "The route-distinguisher command configures a route distinguisher (RD)
+ for the IPv4 or IPv6 address family of a VPN instance.
+
+ Format is ASN:nn or IP-address:nn.";
+
+ config "true";
+ type string {
+ length "3..21";
+ }
+ }
+
+ container vpnTargets {
+ description
+ "The vpn-target command configures the export or import VPN target
+ extended community attribute for the VPN instance IPv4/IPv6 address
+ family.
+ Format is ASN:nn or IP-address:nn.";
+
+ list vpnTarget {
+ key "vrfRTValue";
+ max-elements "unbounded";
+ min-elements "0";
+ description
+ "L3vpn vpntarget configure class";
+
+ leaf vrfRTValue {
+
+ description
+ "Vpn-target: adds VPN target extended community attribute to the
+ export or import VPN target extended community list. The
+ vpn-target can be expressed in either of the following formats:
+ (1)16-bit AS number:32-bit user-defined number
+ For example, 1:3. The AS number ranges from 0 to 65535. The
+ user-defined number ranges from 0 to 4294967295. The AS number
+ and the user-defined number cannot be 0s at the same time.
+ That is, a VPN target cannot be 0:0.
+ (2)32-bit IP address:16-bit user-defined number
+ For example, 192.168.122.15:1. The IP address ranges from
+ 0.0.0.0 to 255.255.255.255. The user-defined number ranges from
+ 0 to 65535.
+ (3)32-bit IP address:16-bit user-defined number
+ For example, 192.168.122.15:1. An IP address ranges from
+ 0.0.0.0 to 255.255.255.255. A user-defined number ranges from 0
+ to 65535.";
+
+ config "true";
+ mandatory "true";
+ type string {
+ length "3..21";
+ }
+ }
+
+ leaf vrfRTType {
+ description
+ "Specifies the vpn target type, export-extcommunity:
+ specifies the extended community attributes carried in routing
+ information to be sent. import-extcommunity: receives routing
+ information carrying specified extended community attributes.";
+
+ mandatory "true";
+ type enumeration {
+ enum export_extcommunity {
+ value "0";
+ description "export-extcommunity:";
+ }
+ enum import_extcommunity {
+ value "1";
+ description "import-extcommunity:";
+ }
+ enum both {
+ value "2";
+ description "export-extcommunity & import-extcommunity:";
+ }
+ }
+ }
+ }
+ }
+
+ container apply-label {
+ description
+ "Apply one label mode for the VPN instance route.";
+
+ choice apply-label-mode {
+ case per-route {
+ description
+ "The apply-label per-route command enables the one-label-per-route
+ mode. The VPN instance IPv4/IPv6 address family assigns a unique
+ label to each route to be sent to the peer PE.";
+
+ leaf apply-label-per-route {
+ type boolean;
+ default "true";
+ }
+ }
+ case per-instance {
+ description
+ "The apply-label per-instance command applies one label to all VPN
+ instance IPv4 address family or IPv6 address family routes to a
+ peer PE.";
+
+ leaf apply-label-per-instance {
+ type boolean;
+ default "false";
+ }
+ }
+ }
+ }//End of "container apply-label"
+
+ leaf import-route-policy {
+ description
+ "The import route-policy command associates a VPN instance enabled
+ with the IPv4 or IPv6 address family with an import routing policy.
+ Only one import routing policy can be associated with a VPN instance
+ enabled with the IPv4 or IPv6 address family. If the import
+ route-policy command is run more than once, the latest configuration
+ overrides the previous ones.";
+
+ config "true";
+ type string {
+ length "1..40";
+ }
+ }
+
+ leaf export-route-policy {
+ description
+ "The export route-policy command associates a VPN instance enabled
+ with the IPv4 or IPv6 address family with an export routing policy.
+ Only one export routing policy can be associated with a VPN instance
+ enabled with the IPv4 or IPv6 address family. If the export
+ route-policy command is run more than once, the latest configuration
+ overrides the previous ones.";
+
+ config "true";
+ type string {
+ length "1..40";
+ }
+ }
+
+
+ container prefix-limit {
+ description
+ "The prefix limit command sets a limit on the maximum number of
+ prefixes supported in the existing VPN instance, preventing the
+ PE from importing excessive VPN route prefixes.";
+
+ leaf prefix-limit-number {
+ description
+ "Specifies the maximum number of prefixes supported in the VPN
+
+
+ instance IPv4 or IPv6 address family.";
+
+ type uint32 {
+ range "1..4294967295";
+ }
+ }
+
+ choice prefix-limit-action {
+ case enable-alert-percent {
+ leaf alert-percent-value {
+ description
+ "Specifies the proportion of the alarm threshold to the maximum
+ number of prefixes.";
+ type uint8 {
+ range "1..100";
+ }
+ }
+ leaf route-unchanged {
+ description
+ "Indicates that the routing table remains unchanged. By default,
+ route-unchanged is not configured. When the number of prefixes
+ in the routing table is greater than the value of the parameter
+ number, routes are processed as follows:
+ (1)If route-unchanged is configured, routes in the routing table
+ remain unchanged.
+ (2)If route-unchanged is not configured, all routes in the
+ routing table are deleted and then re-added.";
+
+ config "true";
+ type boolean;
+ default "false";
+ }
+ }
+ case enable-simple-alert {
+ leaf simple-alert {
+ description
+ "Indicates that when the number of VPN route prefixes exceeds
+ number, prefixes can still join the VPN routing table and
+ alarms are displayed.";
+
+ config "true";
+ type boolean;
+ default "false";
+ }
+ }
+ }
+ }
+
+
+
+ container routing-table-limit {
+ description
+ "The routing-table limit command sets a limit on the maximum number of
+ routes that the IPv4 or IPv6 address family of a VPN instance can
+ support.
+ By default, there is no limit on the maximum number of routes that the
+ IPv4 or IPv6 address family of a VPN instance can support, but the
+ total number of private network and public network routes on a device
+ cannot exceed the allowed maximum number of unicast routes.";
+
+ leaf routing-table-limit-number {
+ description
+ "Specifies the maximum number of routes supported by a VPN instance.
+ ";
+
+ config "true";
+ type uint32 {
+ range "1..4294967295";
+ }
+ }
+ choice routing-table-limit-action {
+ case enable-alert-percent {
+ leaf alert-percent-value {
+ description
+ "Specifies the percentage of the maximum number of routes. When
+ the maximum number of routes that join the VPN instance is up
+ to the value (number*alert-percent)/100, the system prompts
+ alarms. The VPN routes can be still added to the routing table,
+ but after the number of routes reaches number, the subsequent
+ routes are dropped.";
+
+ config "true";
+ type uint8 {
+ range "1..100";
+ }
+ }
+ }
+ case enable-simple-alert {
+ leaf simple-alert {
+ description
+ "Indicates that when VPN routes exceed number, routes can still
+ be added into the routing table, but the system prompts alarms.
+ However, after the total number of VPN routes and network public
+ routes reaches the unicast route limit specified in the License,
+ the subsequent VPN routes are dropped.";
+
+ config "true";
+ type boolean;
+
+ }
+ }
+ }
+ }
+
+ leaf vpn-frr {
+ description
+ "Enable VPN FRR in the VPN instance address family view.
+ If a PE is connected to two other PEs, running the vpn frr command in
+ the VPN instance address family view of the PE enables VPN FRR and
+ improves network reliability. After VPN FRR is configured, traffic can
+ switch to the secondary LSP immediately after the primary LSP becomes
+ faulty.";
+
+ type boolean;
+ default "false";
+ }
+
+
+ /*
+ * VPN QoS.
+ */
+ container l3vpnVrfPipe {
+ description
+ "The diffserv-mode command configures the mode of the MPLS
+ differentiated service (Diff-Serv) for ensuring end-to-end QoS.";
+
+ leaf pipeMode {
+ description
+ "Pipe mode";
+
+ type enumeration {
+ enum pipe {
+ value "0";
+ description
+ "pipe: Indicates that the Pipe MPLS Diff-Serv mode is adopted.";
+ }
+ enum shortPipe {
+ value "1";
+ description
+ "shortPipe: Indicates that the Short-pipe MPLS Diff-Serv mode
+ is adopted.";
+ }
+ enum uniform {
+ value "2";
+ description
+ "uniform: Indicates that the Uniform MPLS Diff-Serv mode is
+ adopted.";
+ }
+ }
+ default "uniform";
+
+ }
+
+ leaf serviceClass {
+ description
+ "Service Class, Specifies the service type when the packet enters the
+ public network from the private network. The values are cs7, cs6, ef,
+ af4, af3, af2, af1, be.";
+
+ type enumeration {
+ enum be {
+ value "0";
+ description "be:";
+ }
+ enum af1 {
+ value "1";
+ description "af1:";
+ }
+ enum af2 {
+ value "2";
+ description "af2:";
+ }
+ enum af3 {
+ value "3";
+ description "af3:";
+ }
+ enum af4 {
+ value "4";
+ description "af4:";
+ }
+ enum ef {
+ value "5";
+ description "ef:";
+ }
+ enum cs6 {
+ value "6";
+ description "cs6:";
+ }
+ enum cs7 {
+ value "7";
+ description "cs7:";
+ }
+ }
+ default "be";
+ }
+
+
+ leaf color {
+ description
+ "Specifies a color for marking the discard priority of a packet
+ transferred from a private network to a public network. The values
+ are green, yellow, and red.";
+
+ type enumeration {
+ enum green {
+ value "0";
+ description "green:";
+ }
+ enum yellow {
+ value "1";
+ description "yellow:";
+ }
+ enum red {
+ value "2";
+ description "red:";
+ }
+ }
+ default "green";
+ }
+
+ leaf dsName {
+ description
+ "Specifies the DS domain name of the specified Per-Hop Behavior (PHB)
+ applied to the egress in Short pipe mode. It is a string of 1 to 31
+ characters.";
+
+ type string;
+ default "default";
+ }
+ }
+
+ container l3vpnTtlMode {
+ description
+ "The ttl-mode command enables MPLS to process the TTL in a specified
+ mode. By default, MPLS processes the TTL in pipe mode.";
+
+ leaf ttlMode {
+ description "TTL mode";
+ default "pipe";
+ type enumeration {
+ enum pipe {
+ value "0";
+ description
+ "pipe: Enables MPLS to process the TTL in pipe mode.";
+ }
+
+
+ enum uniform {
+ value "1";
+ description
+ "uniform: Enables MPLS to process the TTL in uniform mode.";
+ }
+ }
+ }
+ }
+
+ leaf tunnel-policy {
+ description
+ "The tnl-policy command associates the IPv4 or IPv6 address family of
+ a VPN instance with a tunnel policy.";
+
+ type string {
+ length "1..39";
+ }
+ }
+
+ container importRibs {
+ description
+ "Import route class";
+
+ leaf protocol {
+ description
+ "Specifies the protocol from which routes are imported.
+ At present, In the IPv4 unicast address family view, the protocol
+ can be IS-IS,static, direct and BGP.";
+
+ type enumeration {
+ enum ALL {
+ value "0";
+ description "ALL:";
+ }
+ enum Direct {
+ value "1";
+ description "Direct:";
+ }
+ enum OSPF {
+ value "2";
+ description "OSPF:";
+ }
+ enum ISIS {
+ value "3";
+ description "ISIS:";
+ }
+ enum Static {
+ value "4";
+
+
+ description "Static:";
+ }
+ enum RIP {
+ value "5";
+ description "RIP:";
+ }
+ enum BGP {
+ value "6";
+ description "BGP:";
+ }
+ enum OSPFV3 {
+ value "7";
+ description "OSPFV3:";
+ }
+ enum RIPNG {
+ value "8";
+ description "RIPNG:";
+ }
+ enum INVALID {
+ value "9";
+ description "INVALID:";
+ }
+ }
+ }
+
+ leaf processId {
+ description
+ "Specifies the process ID if the protocol from routes are imported is
+ IS-IS.";
+
+ default "0";
+ type uint32 {
+ range "0..4294967295";
+ }
+ }
+
+ leaf bgp-valid-route {
+ type boolean;
+ }
+
+ leaf policyName {
+ description
+ "Policy Id for import routes";
+ type string {
+ }
+ }
+
+ }
+
+
+ leaf traffic-statistics {
+ description
+ "The traffic-statistics enable command enables traffic statistics
+ for a VPN instance.";
+
+ type boolean;
+ default "false";
+ }
+
+ }
+
+
+ /*
+ * VPN instance view.
+ */
+ container vpn-instances {
+ description
+ "VPN instances configuration parameters.
+ VPN instances support both the IPv4 and IPv6 address families.";
+
+ list vpn-instance {
+ max-elements "unbounded";
+ min-elements "0";
+ key "vpn-instance-name";
+ description
+ "Specifies the name of the VPN instance. It is a string of 1 to 31
+ case-sensitive characters.";
+
+ leaf vpn-instance-name {
+ mandatory "true";
+ type string;
+ description
+ "The name of the vpn-instance.";
+ }
+
+ leaf description {
+ description
+ "A textual description of VPN instance, the VPN instance description
+ helps users memorize the VPN instance.";
+
+ type string {
+ length "1..242";
+ pattern "([^?]*)";
+ }
+ }
+
+
+
+
+ container ipv4-family {
+ description
+ "The IPv4 address family is enabled for the VPN instance.";
+
+ uses vpn-af-config;
+ }
+
+ container ipv6-family {
+ description
+ "The IPv6 address family is enabled for the VPN instance.";
+
+ uses vpn-af-config;
+ }
+
+
+ }
+ }
+
+
+
+ /*
+ * Binding Interfaces to a VPN Instance.
+ */
+
+ container vpn-interfaces {
+ description
+ "VPN is enabled on interfaces.";
+
+ list vpn-interface {
+ key "name";
+ max-elements "unbounded";
+ min-elements "0";
+ leaf name {
+ type leafref {
+ path "/if:interfaces/if:interface/if:name";
+ }
+ }
+ leaf vpn-instance-name {
+ type string {
+ length "1..40";
+ }
+ }
+ }
+ }
+
+ container vrfInfo {
+ description
+ "Display the information of the vrf.
+
+
+ It is intended that this container may be augmented by vendors to
+ reflect the vendor-specific operational state parameters.";
+
+ leaf vrfCreateTime {
+ description
+ "CreateTime of the vrf.";
+ config "false";
+ type yang:timestamp;
+ }
+
+ leaf vrfUpTime {
+ description
+ "UpTime period of the vrf.";
+ config "false";
+ type yang:timeticks;
+ }
+
+ leaf label {
+ description
+ "Label of the vrf.";
+ config "false";
+ type uint32 {
+ range "16..1048574";
+ }
+ }
+
+ leaf vrfStatus {
+ description
+ "vrf status.";
+ config "false";
+ type enumeration {
+ enum up {
+ value "0";
+ description "vrf up.";
+ }
+ enum down {
+ value "1";
+ description "vrf down.";
+ }
+ }
+ }
+ }
+
+
+ /*
+ * augment some bgp vpn functions in bgp module.
+ */
+ augment "/bgp:bgp-router/bgp:vpnv4/bgp:unicast" {
+
+ uses augment-bgp-af-vpn-config;
+
+ }
+
+ augment "/bgp:bgp-router/bgp:vpnv6/bgp:unicast" {
+ uses augment-bgp-af-vpn-config;
+
+ }
+
+ augment "/bgp:bgp-router" {
+
+ container bgp-af-ipv4-vpn-instances {
+ description
+ "vpn-instances ipv4 address family.";
+ list bgp-af-ipv4-vpn-instance {
+ key "vpn-instance-name";
+ max-elements "unbounded";
+ min-elements "0";
+ leaf vpn-instance-name {
+ type string;
+ }
+ uses bgp-af-vpn-instance-config;
+ }
+ }
+
+ container bgp-af-ipv6-vpn-instances {
+ description
+ "vpn-instances ipv6 address family.";
+ list bgp-af-ipv6-vpn-instance {
+ key "vpn-instance-name";
+ max-elements "unbounded";
+ min-elements "0";
+ leaf vpn-instance-name {
+ type string;
+ }
+ uses bgp-af-vpn-instance-config;
+ }
+ }
+
+ }
+
+
+}
--- /dev/null
+module odl-l3vpn {
+ namespace "urn:opendaylight:l3vpn";
+ prefix odl-l3vpn;
+
+ import yang-ext {prefix ext; revision-date "2013-07-09";}
+ import l3vpn { prefix l3vpn; revision-date "2014-08-15"; }
+ import ietf-yang-types { prefix "yang"; }
+
+ revision "2013-09-11" {
+ description "L3 VPN Service module";
+ }
+
+ grouping adjacency-list{
+ list adjacency{
+ key "ip_address";
+ leaf nextHopIp { type string; }
+ leaf ip_address {type string;}
+ leaf label { type uint32; config "false"; } /* optional */
+ leaf mac_address {type string;} /* optional */
+ }
+ }
+
+ grouping vpn-route-list{
+ leaf-list route-entry-id{
+ type uint32;
+ }
+ }
+
+ augment "/l3vpn:vpn-interfaces/l3vpn:vpn-interface" {
+ ext:augment-identifier "adjacencies";
+ uses adjacency-list;
+ }
+
+ augment "/l3vpn:vpn-interfaces/l3vpn:vpn-interface" {
+ ext:augment-identifier "opState";
+ leaf stateUp {type boolean; config false;}
+ }
+
+ /* Operational DS containers for reverse lookups*/
+ container prefix-to-interface {
+ config false;
+ list vpn-ids {
+ key vpn-id;
+ leaf vpn-id {type uint32;}
+ list prefixes {
+ key ip_address;
+ leaf ip_address {type string;}
+ leaf dpnId {
+ type uint64;
+ }
+ leaf vpn-interface-name {
+ type string;
+ }
+ }
+ }
+ }
+
+ container vpn-to-extraroute {
+ config false;
+ list vpn {
+ key vrf-id;
+ leaf vrf-id {
+ description
+ "The vrf-id command configures a route distinguisher (RD)
+ for the IPv4 or IPv6 address family of a VPN instance or
+ vpn instance name for internal vpn case.";
+ type string;
+ }
+ list extraroute {
+ key prefix;
+ leaf prefix {type string;}
+ leaf nexthop-ip {
+ type string;
+ }
+ }
+ }
+ }
+
+ /* Data models to adhere to restart requirements */
+ container vpn-instance-to-vpn-id {
+ list vpn-instance {
+ key vpn-instance-name;
+ leaf vpn-instance-name {
+ type string;
+ }
+ leaf vpn-id {
+ type uint32;
+ }
+ leaf vrf-id {
+ description
+ "The vrf-id command configures a route distinguisher (RD)
+ for the IPv4 or IPv6 address family of a VPN instance or
+ vpn instance name for internal vpn case.";
+ type string;
+ }
+ }
+ }
+
+ container vpn-instance-op-data {
+ config false;
+ list vpn-instance-op-data-entry {
+ key vrf-id;
+ leaf vpn-id { type uint32;}
+ leaf vrf-id {
+ description
+ "The vrf-id command configures a route distinguisher (RD)
+ for the IPv4 or IPv6 address family of a VPN instance or
+ vpn instance name for internal vpn case.";
+ type string;
+ }
+
+ leaf vpn-interface-count { type uint32; }
+ uses vpn-route-list;
+ list vpn-to-dpn-list {
+ key dpnId;
+ leaf dpnId {
+ type uint64;
+ }
+ list vpn-interfaces {
+ key interface-name;
+ leaf interface-name {
+ type string;
+ }
+ }
+ list ip-addresses {
+ key ip-address;
+ leaf ip-address {
+ type string;
+ }
+ }
+ }
+ }
+ }
+
+ typedef task-state {
+ type enumeration {
+ enum na {
+ value "0";
+ description
+ "Task not applicable";
+ }
+ enum pending {
+ value "1";
+ description
+ "Task is in pending state";
+ }
+ enum done {
+ value "2";
+ description
+ "Task has been completed";
+ }
+ }
+ description
+ "This value the status of any task.
+ The possible values are NA, PENDING or DONE.
+ ";
+ }
+
+
+ container subnet-op-data {
+ list subnet-op-data-entry {
+ key subnet-id;
+ leaf subnet-id {
+ type yang:uuid;
+ description "UUID representing the subnet ";
+ }
+ leaf nh-dpnId {
+ type uint64;
+ description "DpnId for the DPN used as nexthop for this subnet";
+ }
+ leaf vpn-name {
+ type string;
+ description "VPN Instance name";
+ }
+ leaf vrf-id {
+ type string;
+ }
+ leaf subnet-cidr {
+ type string;
+ description "Subnet in cidr notation";
+ }
+ leaf route-adv-state {
+ type task-state;
+ description "The status of the subnet route advertisement. Route advertisement could be in a NA, PENDING or DONE state.";
+ }
+ leaf elan-tag{
+ type uint32;
+ }
+ list subnet-to-dpn {
+ key dpnId;
+ leaf dpnId {
+ type uint64;
+ }
+ list vpn-interfaces {
+ key interface-name;
+ leaf interface-name {
+ type string;
+ }
+ }
+ }
+
+ }
+ }
+
+ container port-op-data {
+ list port-op-data-entry {
+ key port-id;
+ leaf port-id {
+ type string;
+ description "UUID in string format representing the port ";
+ }
+ leaf subnet-id {
+ type yang:uuid;
+ description "Back reference to obtain the subnet for a port ";
+ }
+ leaf dpnId {
+ type uint64;
+ }
+ }
+ }
+
+ container rd-to-elan-op{
+ list rd-to-elan-op-entry{
+ key "rd subnet-ip";
+ leaf rd {
+ type string;
+ }
+ leaf subnet-ip {
+ type string;
+ }
+ leaf next-hop-ip {
+ type string;
+ }
+ leaf vpn-name {
+ type string;
+ }
+ leaf elan-tag{
+ type uint32;
+ }
+ }
+ }
+
+ grouping dpn-in-vpn-event {
+ leaf dpn-id { type uint64; }
+ leaf vpn-name { type string; }
+ leaf rd { type string; }
+ }
+
+ notification add-dpn-event {
+ container add-event-data {
+ uses dpn-in-vpn-event;
+ }
+ }
+
+ notification remove-dpn-event {
+ container remove-event-data {
+ uses dpn-in-vpn-event;
+ }
+ }
+
+
+ /* container to maintain mapping between neutron router and DPN(s) on which vpn-interfaces for router are present */
+ container neutron-router-dpns {
+ list router-dpn-list {
+ key router-id;
+ leaf router-id { type string;}
+ list dpn-vpninterfaces-list {
+ key dpn-id;
+ leaf dpn-id { type uint64;}
+ list router-interfaces {
+ key interface;
+ leaf interface { type string; }
+ }
+ }
+ }
+ }
+
+
+ container router-interfaces {
+ list router-interface {
+ key interface-name;
+ leaf interface-name { type string; }
+ leaf router-name { type string; }
+ }
+ }
+
+}
--- /dev/null
+module vpn-rpc {\r
+ namespace "urn:opendaylight:vpnservice:vpn:rpc";\r
+ prefix "vpn-rpc";\r
+\r
+ revision "2016-02-01" {\r
+ description "VPN Service RPC Module";\r
+ }\r
+\r
+ /* RPCs */\r
+\r
+ rpc generate-vpn-label {\r
+ description "to generate label for the given ip prefix from the associated VPN";\r
+ input {\r
+ leaf vpn-name {\r
+ type string;\r
+ }\r
+ leaf ip-prefix {\r
+ type string;\r
+ }\r
+ }\r
+ output {\r
+ leaf label {\r
+ type uint32;\r
+ }\r
+ }\r
+ }\r
+\r
+ rpc remove-vpn-label {\r
+ description "to remove label for the given ip prefix from the associated VPN";\r
+ input {\r
+ leaf vpn-name {\r
+ type string;\r
+ }\r
+ leaf ip-prefix {\r
+ type string;\r
+ }\r
+ }\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+module vpnmanager-api {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:vpnmanager:api";
+ prefix "vpnmanager-api";
+
+ import config { prefix config; revision-date 2013-04-05; }
+
+ description
+ "Service definition for vpnmanager project";
+
+ revision "2015-05-08" {
+ description
+ "Initial revision";
+ }
+
+ identity vpnmanager-api {
+ base "config:service-type";
+ config:java-class "org.opendaylight.vpnmanager.api.IVpnManager";
+ }
+}
\ 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) 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,
+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.3.0-SNAPSHOT</version>
+ <relativePath>../../commons/config-parent</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>vpnmanager-impl</artifactId>
+ <version>${vpnservices.version}</version>
+ <packaging>bundle</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>vpnmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>bgpmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>fibmanager-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>${project.groupId}</groupId>
+ <artifactId>itm-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>arputil-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>neutronvpn-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>elanmanager-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ </dependency>
+ </dependencies>
+
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+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,
+and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<snapshot>
+ <required-capabilities>
+ <capability>urn:opendaylight:params:xml:ns:yang:vpnservice:impl?module=vpnservice-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:bgpmanager:api?module=bgpmanager-api&revision=2015-04-20</capability>
+ <capability>urn:opendaylight:params:xml:ns:yang:mdsalutil:api?module=odl-mdsalutil&revision=2015-04-10</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:vpnservice:impl">prefix:vpnservice-impl</type>
+ <name>vpnservice-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>
+ <bgpmanager>
+ <type xmlns:bgpmanager="urn:opendaylight:params:xml:ns:yang:bgpmanager:api">bgpmanager:bgpmanager-api</type>
+ <name>bgpmanager</name>
+ </bgpmanager>
+ <mdsalutil>
+ <type xmlns:mdsalutil="urn:opendaylight:params:xml:ns:yang:mdsalutil:api">mdsalutil:odl-mdsalutil</type>
+ <name>mdsalutil-service</name>
+ </mdsalutil>
+ <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:vpnmanager:api">prefix:vpnmanager-api</type>
+ <instance>
+ <name>vpnmanager</name>
+ <provider>/modules/module[type='vpnservice-impl'][name='vpnservice-default']</provider>
+ </instance>
+ </service>
+ </services>
+ </data>
+ </configuration>
+</snapshot>
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * AbstractDataChangeListener implemented basic {@link DataChangeListener} processing for
+ * VPN related Data Objects.
+ */
+public abstract class AbstractDataChangeListener<T extends DataObject> implements DataChangeListener {
+
+ protected final Class<T> clazz;
+
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractDataChangeListener.class);
+ /**
+ *
+ * @param clazz - for which the data change event is received
+ */
+ public AbstractDataChangeListener(Class<T> clazz) {
+ this.clazz = Preconditions.checkNotNull(clazz, "Class can not be null!");
+ }
+
+ @Override
+ public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> changeEvent) {
+ try {
+ Preconditions.checkNotNull(changeEvent,"Async ChangeEvent can not be null!");
+
+ /* All DataObjects for create */
+ final Map<InstanceIdentifier<?>, DataObject> createdData = changeEvent.getCreatedData() != null
+ ? changeEvent.getCreatedData() : Collections.<InstanceIdentifier<?>, DataObject>emptyMap();
+ /* All DataObjects for remove */
+ final Set<InstanceIdentifier<?>> removeData = changeEvent.getRemovedPaths() != null
+ ? changeEvent.getRemovedPaths() : Collections.<InstanceIdentifier<?>>emptySet();
+ /* All DataObjects for updates */
+ final Map<InstanceIdentifier<?>, DataObject> updateData = changeEvent.getUpdatedData() != null
+ ? changeEvent.getUpdatedData() : Collections.<InstanceIdentifier<?>, DataObject>emptyMap();
+ /* All Original DataObjects */
+ final Map<InstanceIdentifier<?>, DataObject> originalData = changeEvent.getOriginalData() != null
+ ? changeEvent.getOriginalData() : Collections.<InstanceIdentifier<?>, DataObject>emptyMap();
+
+ this.createData(createdData);
+ this.updateData(updateData, originalData);
+ this.removeData(removeData, originalData);
+
+ } catch (Throwable e) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("failed to handle dcn ", e);
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void createData(final Map<InstanceIdentifier<?>, DataObject> createdData) {
+ final Set<InstanceIdentifier<?>> keys = createdData.keySet() != null
+ ? createdData.keySet() : Collections.<InstanceIdentifier<?>>emptySet();
+ for (InstanceIdentifier<?> key : keys) {
+ if (clazz.equals(key.getTargetType())) {
+ InstanceIdentifier<T> createKeyIdent = key.firstIdentifierOf(clazz);
+ final Optional<DataObject> value = Optional.of(createdData.get(key));
+ if (value.isPresent()) {
+ this.add(createKeyIdent, (T)value.get());
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void updateData(final Map<InstanceIdentifier<?>, DataObject> updateData,
+ final Map<InstanceIdentifier<?>, DataObject> originalData) {
+
+ final Set<InstanceIdentifier<?>> keys = updateData.keySet() != null
+ ? updateData.keySet() : Collections.<InstanceIdentifier<?>>emptySet();
+ for (InstanceIdentifier<?> key : keys) {
+ if (clazz.equals(key.getTargetType())) {
+ InstanceIdentifier<T> updateKeyIdent = key.firstIdentifierOf(clazz);
+ final Optional<DataObject> value = Optional.of(updateData.get(key));
+ final Optional<DataObject> original = Optional.of(originalData.get(key));
+ if (value.isPresent() && original.isPresent()) {
+ this.update(updateKeyIdent, (T)original.get(), (T)value.get());
+ }
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void removeData(final Set<InstanceIdentifier<?>> removeData,
+ final Map<InstanceIdentifier<?>, DataObject> originalData) {
+
+ for (InstanceIdentifier<?> key : removeData) {
+ if (clazz.equals(key.getTargetType())) {
+ final InstanceIdentifier<T> ident = key.firstIdentifierOf(clazz);
+ final DataObject removeValue = originalData.get(key);
+ this.remove(ident, (T)removeValue);
+ }
+ }
+ }
+
+ protected abstract void remove(InstanceIdentifier<T> identifier, T del);
+
+ protected abstract void update(InstanceIdentifier<T> identifier, T original, T update);
+
+ protected abstract void add(InstanceIdentifier<T> identifier, T add);
+
+}
+
+
--- /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;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.ArpRequestReceived;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.ArpResponseReceived;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.MacChanged;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ArpNotificationHandler implements OdlArputilListener {
+
+ VpnInterfaceManager vpnIfManager;
+ DataBroker broker;
+
+ private static final Logger LOG = LoggerFactory.getLogger(ArpNotificationHandler.class);
+
+ public ArpNotificationHandler(VpnInterfaceManager vpnIfMgr, DataBroker dataBroker) {
+ vpnIfManager = vpnIfMgr;
+ broker = dataBroker;
+ }
+
+ public void onMacChanged(MacChanged notification){
+
+ }
+
+ public void onArpRequestReceived(ArpRequestReceived notification){
+ String srcInterface = notification.getInterface();
+ IpAddress srcIP = notification.getSrcIpaddress();
+ PhysAddress srcMac = notification.getSrcMac();
+ IpAddress targetIP = notification.getDstIpaddress();
+
+ // Respond to ARP request only if vpnservice is configured on the interface
+ if(VpnUtil.isVpnInterfaceConfigured(broker, srcInterface)) {
+ LOG.info("Received ARP Request for interface {} ", srcInterface);
+ vpnIfManager.processArpRequest(srcIP, srcMac, targetIP, srcInterface);
+ }
+ }
+
+ public void onArpResponseReceived(ArpResponseReceived notification){
+
+ }
+
+}
--- /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;
+
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+
+public enum ArpReplyOrRequest {
+ REQUEST("ARP-REQUEST"), REPLY("ARP-REPLY");
+
+ private String name;
+
+ ArpReplyOrRequest(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public int getArpOperation(){
+ int arpOperation = (name == ArpReplyOrRequest.REQUEST.getName() ? NwConstants.ARP_REQUEST : NwConstants.ARP_REPLY);
+ return arpOperation;
+ }
+ public int calculateConsistentHashCode() {
+ if (this.name != null) {
+ return this.name.hashCode();
+ } else {
+ return 0;
+ }
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice;
+
+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.utilities.InterfaceUtils;
+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.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.router.interfaces.RouterInterface;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+
+public class InterfaceStateChangeListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateChangeListener.class);
+
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker broker;
+ private VpnInterfaceManager vpnInterfaceManager;
+ private OdlInterfaceRpcService interfaceManager;
+
+
+ public InterfaceStateChangeListener(final DataBroker db, VpnInterfaceManager vpnInterfaceManager) {
+ super(Interface.class);
+ broker = db;
+ this.vpnInterfaceManager = vpnInterfaceManager;
+ registerListener(db);
+ }
+
+ public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
+ this.interfaceManager = interfaceManager;
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ LOG.info("Interface listener Closed");
+ }
+
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), InterfaceStateChangeListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("Interface DataChange listener registration failed", e);
+ throw new IllegalStateException("Nexthop Manager registration Listener failed.", e);
+ }
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
+ LOG.trace("Received interface {} up event", intrf);
+ try {
+ String interfaceName = intrf.getName();
+ LOG.info("Received port UP event for interface {} ", interfaceName);
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
+ configInterface = InterfaceUtils.getInterface(broker, interfaceName);
+ BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(intrf);
+ if (configInterface != null && configInterface.getType().equals(Tunnel.class)) {
+ if(intrf.getOperStatus().equals(Interface.OperStatus.Up)) {
+ //advertise all prefixes in all vpns for this dpn to bgp
+ // FIXME: Blocked until tunnel event[vxlan/gre] support is available
+ // vpnInterfaceManager.updatePrefixesForDPN(dpnId, VpnInterfaceManager.UpdateRouteAction.ADVERTISE_ROUTE);
+ }
+ } else {
+ vpnInterfaceManager.processVpnInterfaceUp(dpnId, interfaceName, intrf.getIfIndex());
+ vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceUp(intrf);
+ handleRouterInterfacesUpEvent(interfaceName);
+ }
+ } catch (Exception e) {
+ LOG.error("Exception caught in Interface Operational State Up event", e);
+ }
+ }
+
+
+ private InstanceIdentifier<Interface> getWildCardPath() {
+ return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Interface> identifier, Interface intrf) {
+ LOG.trace("Received interface {} down event", intrf);
+ try {
+ String interfaceName = intrf.getName();
+ LOG.info("Received port DOWN event for interface {} ", interfaceName);
+ BigInteger dpId = InterfaceUtils.getDpIdFromInterface(intrf);
+ if (intrf != null && intrf.getType() != null && intrf.getType().equals(Tunnel.class)) {
+ //withdraw all prefixes in all vpns for this dpn from bgp
+ // FIXME: Blocked until tunnel event[vxlan/gre] support is available
+ // vpnInterfaceManager.updatePrefixesForDPN(dpId, VpnInterfaceManager.UpdateRouteAction.WITHDRAW_ROUTE);
+ } else {
+ if (VpnUtil.isVpnInterfaceConfigured(broker, interfaceName)) {
+ vpnInterfaceManager.processVpnInterfaceDown(dpId, interfaceName, intrf.getIfIndex(), true);
+ vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceDown(intrf);
+ handleRouterInterfacesDownEvent(interfaceName,dpId);
+ }
+ }
+ } catch (Exception e) {
+ LOG.error("Exception caught in onVlanInterfaceOperationalStateDown", e);
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Interface> identifier,
+ Interface original, Interface update) {
+ LOG.trace("Operation Interface update event - Old: {}, New: {}", original, update);
+ String interfaceName = update.getName();
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
+ intf = InterfaceUtils.getInterface(broker, interfaceName);
+ if (intf != null && intf.getType().equals(Tunnel.class)) {
+ /*
+ // FIXME: Blocked until tunnel event[vxlan/gre] support is available
+ BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(update);
+ if(update.getOperStatus().equals(Interface.OperStatus.Up)) {
+ //advertise all prefixes in all vpns for this dpn to bgp
+ // vpnInterfaceManager.updatePrefixesForDPN(dpnId, VpnInterfaceManager.UpdateRouteAction.ADVERTISE_ROUTE);
+ vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceUp(update);
+ } else if(update.getOperStatus().equals(Interface.OperStatus.Down)) {
+ //withdraw all prefixes in all vpns for this dpn from bgp
+ // vpnInterfaceManager.updatePrefixesForDPN(dpnId, VpnInterfaceManager.UpdateRouteAction.WITHDRAW_ROUTE);
+ vpnInterfaceManager.getVpnSubnetRouteHandler().onInterfaceDown(update);
+ }*/
+ }
+
+ }
+
+ void handleRouterInterfacesUpEvent(String interfaceName) {
+ Optional<RouterInterface> optRouterInterface = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, VpnUtil.getRouterInterfaceId(interfaceName));
+ if(optRouterInterface.isPresent()) {
+ RouterInterface routerInterface = optRouterInterface.get();
+ String routerName = routerInterface.getRouterName();
+ LOG.debug("Handling UP event for router interface {} in Router {}", interfaceName, routerName);
+ vpnInterfaceManager.addToNeutronRouterDpnsMap(routerName, interfaceName);
+ } else {
+ LOG.debug("No Router interface configured to handle UP event for {}", interfaceName);
+ }
+ }
+
+ void handleRouterInterfacesDownEvent(String interfaceName,BigInteger dpnId) {
+ Optional<RouterInterface> optRouterInterface = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, VpnUtil.getRouterInterfaceId(interfaceName));
+ if(optRouterInterface.isPresent()) {
+ RouterInterface routerInterface = optRouterInterface.get();
+ String routerName = routerInterface.getRouterName();
+ LOG.debug("Handling DOWN event for router interface {} in Router {}", interfaceName, routerName);
+ vpnInterfaceManager.removeFromNeutronRouterDpnsMap(routerName, interfaceName,dpnId);
+ } else {
+ LOG.debug("No Router interface configured to handle DOWN event for {}", interfaceName);
+ }
+ }
+
+}
--- /dev/null
+/*\r
+ * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.vpnservice;\r
+\r
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;\r
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;\r
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;\r
+import org.opendaylight.vpnservice.utilities.InterfaceUtils;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.RouterInterfacesMap;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.router.interfaces.map.RouterInterfaces;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.router.interfaces.map.router.interfaces.Interfaces;\r
+import org.opendaylight.yangtools.concepts.ListenerRegistration;\r
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+public class RouterInterfaceListener extends AbstractDataChangeListener<Interfaces> {\r
+ private static final Logger LOG = LoggerFactory.getLogger(RouterInterfaceListener.class);\r
+ private ListenerRegistration<DataChangeListener> listenerRegistration;\r
+ private DataBroker broker;\r
+ private VpnInterfaceManager vpnInterfaceManager;\r
+\r
+ public RouterInterfaceListener(final DataBroker db) {\r
+ super(Interfaces.class);\r
+ broker = db;\r
+ registerListener(db);\r
+ }\r
+\r
+ void setVpnInterfaceManager(VpnInterfaceManager vpnInterfaceManager) {\r
+ this.vpnInterfaceManager = vpnInterfaceManager;\r
+ }\r
+\r
+ private void registerListener(final DataBroker db) {\r
+ try {\r
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,\r
+ getWildCardPath(), RouterInterfaceListener.this, DataChangeScope.SUBTREE);\r
+ } catch (final Exception e) {\r
+ LOG.error("Router interface DataChange listener registration fail !", e);\r
+ }\r
+ }\r
+\r
+ private InstanceIdentifier<?> getWildCardPath() {\r
+ return InstanceIdentifier.create(RouterInterfacesMap.class).child(RouterInterfaces.class).child(Interfaces.class);\r
+ }\r
+\r
+ @Override\r
+ protected void add(InstanceIdentifier<Interfaces> identifier, Interfaces interfaceInfo) {\r
+ LOG.trace("Add event - key: {}, value: {}", identifier, interfaceInfo);\r
+ final String routerId = identifier.firstKeyOf(RouterInterfaces.class).getRouterId().getValue();\r
+ String interfaceName = interfaceInfo.getInterfaceId();\r
+\r
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, \r
+ VpnUtil.getRouterInterfaceId(interfaceName), VpnUtil.getRouterInterface(interfaceName, routerId));\r
+\r
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =\r
+ InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);\r
+ if (interfaceState != null) {\r
+ LOG.debug("Handling interface {} in router {} add scenario", interfaceName, routerId);\r
+ vpnInterfaceManager.addToNeutronRouterDpnsMap(routerId, interfaceName);\r
+ } else {\r
+ LOG.warn("Interface {} not yet operational to handle router interface add event in router {}", interfaceName, routerId);\r
+ }\r
+ }\r
+\r
+ @Override\r
+ protected void remove(InstanceIdentifier<Interfaces> identifier, Interfaces interfaceInfo) {\r
+ LOG.trace("Remove event - key: {}, value: {}", identifier, interfaceInfo);\r
+ final String routerId = identifier.firstKeyOf(RouterInterfaces.class).getRouterId().getValue();\r
+ String interfaceName = interfaceInfo.getInterfaceId();\r
+ vpnInterfaceManager.removeFromNeutronRouterDpnsMap(routerId, interfaceName);\r
+ }\r
+\r
+ @Override\r
+ protected void update(InstanceIdentifier<Interfaces> identifier, Interfaces original, Interfaces update) {\r
+ LOG.trace("Update event - key: {}, original: {}, update: {}", identifier, original, update);\r
+ }\r
+\r
+}\r
--- /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;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.port.op.data.PortOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.port.op.data.PortOpDataEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.port.op.data.PortOpDataEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.subnet.to.dpn.VpnInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.subnet.to.dpn.VpnInterfacesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.subnet.to.dpn.VpnInterfacesKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.PortOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.SubnetOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpnKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.math.BigInteger;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+
+public class SubnetOpDpnManager {
+ private static final Logger logger = LoggerFactory.getLogger(SubnetOpDpnManager.class);
+
+ private final DataBroker broker;
+
+ public SubnetOpDpnManager(final DataBroker db) {
+ broker = db;
+ }
+
+ private SubnetToDpn addDpnToSubnet(Uuid subnetId, BigInteger dpnId) {
+ SubnetToDpn subDpn = null;
+ try {
+ InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
+ child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
+ InstanceIdentifier<SubnetToDpn> dpnOpId = subOpIdentifier.child(SubnetToDpn.class, new SubnetToDpnKey(dpnId));
+ Optional<SubnetToDpn> optionalSubDpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, dpnOpId);
+ if (optionalSubDpn.isPresent()) {
+ logger.error("Cannot create, SubnetToDpn for subnet " + subnetId.getValue() +
+ " as DPN " + dpnId + " already seen in datastore");
+ return null;
+ }
+ SubnetToDpnBuilder subDpnBuilder = new SubnetToDpnBuilder().setKey(new SubnetToDpnKey(dpnId));
+ List<VpnInterfaces> vpnIntfList = new ArrayList<VpnInterfaces>();
+ subDpnBuilder.setVpnInterfaces(vpnIntfList);
+ subDpn = subDpnBuilder.build();
+ logger.trace("Creating SubnetToDpn entry for subnet " + subnetId.getValue() + " with DPNId "+ dpnId);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, dpnOpId, subDpn);
+ } catch (Exception ex) {
+ logger.error("Creation of SubnetToDpn for subnet " +
+ subnetId.getValue() + " with DpnId " + dpnId + " failed {}" + ex);
+ return null;
+ } finally {
+ }
+ return subDpn;
+ }
+
+ private void removeDpnFromSubnet(Uuid subnetId, BigInteger dpnId) {
+ try {
+ InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
+ child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
+ InstanceIdentifier<SubnetToDpn> dpnOpId =subOpIdentifier.child(SubnetToDpn.class, new SubnetToDpnKey(dpnId));
+ Optional<SubnetToDpn> optionalSubDpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, dpnOpId);
+ if (!optionalSubDpn.isPresent()) {
+ logger.warn("Cannot delete, SubnetToDpn for subnet " + subnetId.getValue() +
+ " DPN " + dpnId + " not available in datastore");
+ return;
+ }
+ logger.trace("Deleting SubnetToDpn entry for subnet " + subnetId.getValue() + " with DPNId "+ dpnId);
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, dpnOpId);
+ } catch (Exception ex) {
+ logger.error("Deletion of SubnetToDpn for subnet " +
+ subnetId.getValue() + " with DPN " + dpnId + " failed {}" + ex);
+ } finally {
+ }
+ }
+
+ public SubnetToDpn addInterfaceToDpn(Uuid subnetId, BigInteger dpnId, String intfName) {
+ SubnetToDpn subDpn = null;
+ try {
+ // Create and add SubnetOpDataEntry object for this subnet to the SubnetOpData container
+ InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
+ child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
+ //Please use a synchronize block here as we donot need a cluster-wide lock
+ InstanceIdentifier<SubnetToDpn> dpnOpId = subOpIdentifier.child(SubnetToDpn.class, new SubnetToDpnKey(dpnId));
+ Optional<SubnetToDpn> optionalSubDpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, dpnOpId);
+ if (!optionalSubDpn.isPresent()) {
+ // Create a new DPN Entry
+ subDpn = addDpnToSubnet(subnetId, dpnId);
+ } else {
+ subDpn = optionalSubDpn.get();
+ }
+ SubnetToDpnBuilder subDpnBuilder = new SubnetToDpnBuilder(subDpn);
+ List<VpnInterfaces> vpnIntfList = subDpnBuilder.getVpnInterfaces();
+ VpnInterfaces vpnIntfs = new VpnInterfacesBuilder().setKey(new VpnInterfacesKey(intfName)).setInterfaceName(intfName).build();
+ vpnIntfList.add(vpnIntfs);
+ subDpnBuilder.setVpnInterfaces(vpnIntfList);
+ subDpn = subDpnBuilder.build();
+
+ logger.trace("Creating SubnetToDpn entry for subnet " + subnetId.getValue() + " with DPNId "+ dpnId);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, dpnOpId, subDpn);
+ } catch (Exception ex) {
+ logger.error("Addition of Interface " + intfName + " for SubnetToDpn on subnet " +
+ subnetId.getValue() + " with DPN " + dpnId + " failed {}" + ex);
+ return null;
+ } finally {
+ }
+ return subDpn;
+ }
+
+ public void addPortOpDataEntry(String intfName, Uuid subnetId, BigInteger dpnId) {
+ try {
+ // Add to PortOpData as well.
+ PortOpDataEntryBuilder portOpBuilder = null;
+ PortOpDataEntry portOpEntry = null;
+
+ InstanceIdentifier<PortOpDataEntry> portOpIdentifier = InstanceIdentifier.builder(PortOpData.class).
+ child(PortOpDataEntry.class, new PortOpDataEntryKey(intfName)).build();
+ Optional<PortOpDataEntry> optionalPortOp = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
+ if (!optionalPortOp.isPresent()) {
+ // Create PortOpDataEntry only if not present
+ portOpBuilder = new PortOpDataEntryBuilder().setKey(new PortOpDataEntryKey(intfName)).setPortId(intfName);
+ portOpBuilder.setSubnetId(subnetId);
+ portOpBuilder.setDpnId(dpnId);
+ portOpEntry = portOpBuilder.build();
+ } else {
+ portOpBuilder = new PortOpDataEntryBuilder(optionalPortOp.get());
+ portOpBuilder.setSubnetId(subnetId);
+ portOpBuilder.setDpnId(dpnId);
+ portOpEntry = portOpBuilder.build();
+ }
+ logger.trace("Creating PortOpData entry for port " + intfName + " with DPNId "+ dpnId);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier, portOpEntry);
+ } catch (Exception ex) {
+ logger.error("Addition of Interface " + intfName + " for SubnetToDpn on subnet " +
+ subnetId.getValue() + " with DPN " + dpnId + " failed {}" + ex);
+ } finally {
+ }
+ }
+
+ public boolean removeInterfaceFromDpn(Uuid subnetId, BigInteger dpnId, String intfName) {
+ boolean dpnRemoved = false;
+ try {
+ InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
+ child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
+ InstanceIdentifier<SubnetToDpn> dpnOpId = subOpIdentifier.child(SubnetToDpn.class, new SubnetToDpnKey(dpnId));
+ Optional<SubnetToDpn> optionalSubDpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, dpnOpId);
+ if (!optionalSubDpn.isPresent()) {
+ logger.warn("Cannot delete, SubnetToDpn for subnet " + subnetId.getValue() +
+ " DPN " + dpnId + " not available in datastore");
+ return false;
+ }
+
+ SubnetToDpnBuilder subDpnBuilder = new SubnetToDpnBuilder(optionalSubDpn.get());
+ List<VpnInterfaces> vpnIntfList = subDpnBuilder.getVpnInterfaces();
+ VpnInterfaces vpnIntfs = new VpnInterfacesBuilder().setKey(new VpnInterfacesKey(intfName)).setInterfaceName(intfName).build();
+ vpnIntfList.remove(vpnIntfs);
+ if (vpnIntfList.isEmpty()) {
+ // Remove the DPN as well
+ removeDpnFromSubnet(subnetId, dpnId);
+ dpnRemoved = true;
+ } else {
+ subDpnBuilder.setVpnInterfaces(vpnIntfList);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, dpnOpId, subDpnBuilder.build());
+ }
+ } catch (Exception ex) {
+ logger.error("Deletion of Interface " + intfName + " for SubnetToDpn on subnet " +
+ subnetId.getValue() + " with DPN " + dpnId + " failed {}" + ex);
+ return false;
+ } finally {
+ }
+ return dpnRemoved;
+ }
+
+ public PortOpDataEntry removePortOpDataEntry(String intfName) {
+ // Remove PortOpData and return out
+ InstanceIdentifier<PortOpDataEntry> portOpIdentifier = InstanceIdentifier.builder(PortOpData.class).
+ child(PortOpDataEntry.class, new PortOpDataEntryKey(intfName)).build();
+ PortOpDataEntry portOpEntry = null;
+ Optional<PortOpDataEntry> optionalPortOp = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
+ if (!optionalPortOp.isPresent()) {
+ logger.error("Cannot delete, portOp for port " + intfName +
+ " is not available in datastore");
+ return null;
+ } else {
+ portOpEntry = optionalPortOp.get();
+ logger.trace("Deleting portOpData entry for port " + intfName);
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
+ }
+ return portOpEntry;
+ }
+
+ public PortOpDataEntry getPortOpDataEntry(String intfName) {
+ // Remove PortOpData and return out
+ InstanceIdentifier<PortOpDataEntry> portOpIdentifier = InstanceIdentifier.builder(PortOpData.class).
+ child(PortOpDataEntry.class, new PortOpDataEntryKey(intfName)).build();
+ Optional<PortOpDataEntry> optionalPortOp = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
+ if (!optionalPortOp.isPresent()) {
+ logger.error("Cannot get, portOp for port " + intfName +
+ " is not available in datastore");
+ return null;
+ }
+ return optionalPortOp.get();
+ }
+
+}
--- /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;
+
+import com.google.common.base.Optional;
+import com.google.common.primitives.Ints;
+import org.opendaylight.controller.liblldp.EtherTypes;
+import org.opendaylight.controller.liblldp.NetUtils;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+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.l3vpn.rev130911.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.SubnetOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+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.neutronvpn.rev150602.NetworkMaps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.networkmaps.NetworkMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.networkmaps.NetworkMapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.tag.name.map.ElanTagName;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.vpnservice.mdsalutil.packet.ARP;
+import org.opendaylight.vpnservice.mdsalutil.packet.IPv4;
+import org.opendaylight.vpnservice.mdsalutil.packet.Ethernet;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.controller.liblldp.Packet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.List;
+import java.nio.charset.StandardCharsets;
+import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
+import org.opendaylight.vpnservice.mdsalutil.ActionType;
+import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+
+public class SubnetRoutePacketInHandler implements PacketProcessingListener {
+
+ private static final Logger s_logger = LoggerFactory.getLogger(SubnetRoutePacketInHandler.class);
+ private final DataBroker broker;
+ private PacketProcessingService packetService;
+ private VpnInterfaceManager ifManager;
+ private IdManagerService idManager;
+ //List maintains info about the arp request sent - id src+dst ip
+ private ArrayList<String> arpList = new ArrayList();
+
+ public SubnetRoutePacketInHandler(DataBroker dataBroker, IdManagerService idManager) {
+ broker = dataBroker;
+ this.idManager = idManager;
+ }
+
+ public void onPacketReceived(PacketReceived notification) {
+
+ s_logger.trace("SubnetRoutePacketInHandler: PacketReceived invoked...");
+
+ short tableId = notification.getTableId().getValue();
+ byte[] data = notification.getPayload();
+ BigInteger metadata = notification.getMatch().getMetadata().getMetadata();
+ Ethernet res = new Ethernet();
+
+ if (tableId == NwConstants.L3_SUBNET_ROUTE_TABLE) {
+ s_logger.trace("SubnetRoutePacketInHandler: Some packet received as {}", notification);
+ try {
+ res.deserialize(data, 0, data.length * NetUtils.NumBitsInAByte);
+ } catch (Exception e) {
+ s_logger.warn("SubnetRoutePacketInHandler: Failed to decode Packet ", e);
+ return;
+ }
+ try {
+ Packet pkt = res.getPayload();
+ if (pkt instanceof IPv4) {
+ IPv4 ipv4 = (IPv4) pkt;
+ byte[] srcMac = res.getSourceMACAddress();
+ byte[] dstMac = res.getDestinationMACAddress();
+ byte[] srcIp = Ints.toByteArray(ipv4.getSourceAddress());
+ byte[] dstIp = Ints.toByteArray(ipv4.getDestinationAddress());
+ String dstIpStr = toStringIpAddress(dstIp);
+ String srcIpStr = toStringIpAddress(srcIp);
+ if (VpnUtil.getNeutronPortNamefromPortFixedIp(broker, dstIpStr) != null) {
+ s_logger.debug("SubnetRoutePacketInHandler: IPv4 Packet received with "
+ + "Target IP {} is a valid Neutron port, ignoring subnet route processing", dstIpStr);
+ return;
+ }
+ long elanTag = MetaDataUtil.getElanTagFromMetadata(metadata);
+ if (elanTag == 0) {
+ s_logger.error("SubnetRoutePacketInHandler: elanTag value from metadata found to be 0, for IPv4 " +
+ "Packet received with Target IP {}", dstIpStr);
+ return;
+ }
+ s_logger.info("SubnetRoutePacketInHandler: Processing IPv4 Packet received with Source IP {} "
+ + "and Target IP {} and elan Tag {}", srcIpStr, dstIpStr, elanTag);
+ BigInteger dpnId = getTargetDpnForPacketOut(broker, elanTag, ipv4.getDestinationAddress());
+ //Handle subnet routes ip requests
+ if (dpnId != BigInteger.ZERO) {
+ long groupid = VpnUtil.getRemoteBCGroup(elanTag);
+ String key = srcIpStr + dstIpStr;
+ sendArpRequest(dpnId, groupid, srcMac, srcIp, dstIp);
+ }
+ return;
+ }
+ } catch (Exception ex) {
+ //Failed to handle packet
+ s_logger.error("SubnetRoutePacketInHandler: Failed to handle subnetroute packets ", ex);
+ }
+ return;
+ }
+
+ if (tableId == NwConstants.L3_INTERFACE_TABLE) {
+ s_logger.trace("SubnetRoutePacketInHandler: Packet from Table {} received as {}",
+ NwConstants.L3_INTERFACE_TABLE, notification);
+ try {
+ res.deserialize(data, 0, data.length * NetUtils.NumBitsInAByte);
+ } catch (Exception e) {
+ s_logger.warn("SubnetRoutePacketInHandler: Failed to decode Table " + NwConstants.L3_INTERFACE_TABLE + " Packet ", e);
+ return;
+ }
+ try {
+ Packet pkt = res.getPayload();
+ if (pkt instanceof ARP) {
+ s_logger.debug("SubnetRoutePacketInHandler: ARP packet received");
+ ARP arpPacket = (ARP) pkt;
+ boolean arpReply = (arpPacket.getOpCode() == 2) ? true : false;
+ if (arpReply) {
+ //Handle subnet routes arp responses
+ s_logger.debug("SubnetRoutePacketInHandler: ARP reply received");
+ byte[] respSrc = arpPacket.getSenderProtocolAddress();
+ byte[] respDst = arpPacket.getTargetProtocolAddress();
+ String respIp = toStringIpAddress(respSrc);
+ String check = toStringIpAddress(respDst) + respIp;
+ if (VpnUtil.getNeutronPortNamefromPortFixedIp(broker, respIp) != null) {
+ s_logger.debug("SubnetRoutePacketInHandler: ARP reply Packet received with "
+ + "Source IP {} which is a valid Neutron port, ignoring subnet route processing", respIp);
+ return;
+ }
+ String destination = VpnUtil.getIpPrefix(respIp);
+ long portTag = MetaDataUtil.getLportFromMetadata(metadata).intValue();
+ s_logger.info("SubnetRoutePacketInHandler: ARP reply received for target IP {} from LPort {}" + respIp, portTag);
+ IfIndexInterface interfaceInfo = VpnUtil.getInterfaceInfoByInterfaceTag(broker, portTag);
+ String ifName = interfaceInfo.getInterfaceName();
+ InstanceIdentifier<VpnInterface> vpnIfIdentifier = VpnUtil.getVpnInterfaceIdentifier(ifName);
+ VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(broker, ifName);
+
+ //Get VPN interface adjacencies
+ if (vpnInterface != null) {
+ InstanceIdentifier<Adjacencies> path = vpnIfIdentifier.augmentation(Adjacencies.class);
+ Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, path);
+ String nextHopIpAddr = null;
+ String nextHopMacAddress = null;
+ if (adjacencies.isPresent()) {
+ List<Adjacency> adjacencyList = adjacencies.get().getAdjacency();
+ for (Adjacency adjacs : adjacencyList) {
+ if (adjacs.getMacAddress() != null && !adjacs.getMacAddress().isEmpty()) {
+ nextHopIpAddr = adjacs.getIpAddress();
+ nextHopMacAddress = adjacs.getMacAddress();
+ break;
+ }
+ }
+ if (nextHopMacAddress != null && destination != null) {
+ String rd = VpnUtil.getVpnRd(broker, vpnInterface.getVpnInstanceName());
+ long label =
+ VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
+ VpnUtil.getNextHopLabelKey((rd != null) ? rd : vpnInterface.getVpnInstanceName(), destination));
+ String nextHopIp = nextHopIpAddr.split("/")[0];
+ Adjacency newAdj = new AdjacencyBuilder().setIpAddress(destination).setKey
+ (new AdjacencyKey(destination)).setNextHopIp(nextHopIp).build();
+ adjacencyList.add(newAdj);
+ Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencyList);
+ VpnInterface newVpnIntf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(vpnInterface.getName())).
+ setName(vpnInterface.getName()).setVpnInstanceName(vpnInterface.getVpnInstanceName()).
+ addAugmentation(Adjacencies.class, aug).build();
+ VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, newVpnIntf);
+ s_logger.debug("SubnetRoutePacketInHandler: Successfully stored subnetroute Adjacency into VpnInterface {}", newVpnIntf);
+ }
+ }
+ }
+ }
+ }
+ } catch (Exception ex) {
+ //Failed to decode packet
+ s_logger.error("SubnetRoutePacketInHandler: Failed to handle subnetroute Table " + NwConstants.L3_INTERFACE_TABLE +
+ " packets ", ex);
+ }
+ }
+ }
+
+ private static BigInteger getTargetDpnForPacketOut(DataBroker broker, long elanTag, int ipAddress) {
+ BigInteger dpnid = BigInteger.ZERO;
+ ElanTagName elanInfo = VpnUtil.getElanInfoByElanTag(broker, elanTag);
+ if (elanInfo == null) {
+ s_logger.trace("SubnetRoutePacketInHandler: Unable to retrieve ElanInfo for elanTag {}", elanTag);
+ return dpnid;
+ }
+ InstanceIdentifier<NetworkMap> networkId = InstanceIdentifier.builder(NetworkMaps.class)
+ .child(NetworkMap.class, new NetworkMapKey(new Uuid(elanInfo.getName()))).build();
+
+ Optional<NetworkMap> optionalNetworkMap = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, networkId);
+ if (optionalNetworkMap.isPresent()) {
+ List<Uuid> subnetList = optionalNetworkMap.get().getSubnetIdList();
+ s_logger.trace("SubnetRoutePacketInHandler: Obtained subnetList as " + subnetList);
+ for (Uuid subnetId : subnetList) {
+ InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
+ child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
+ Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
+ subOpIdentifier);
+ if (!optionalSubs.isPresent()) {
+ continue;
+ }
+ SubnetOpDataEntry subOpEntry = optionalSubs.get();
+ if (subOpEntry.getNhDpnId() != null) {
+ s_logger.trace("SubnetRoutePacketInHandler: Viewing Subnet " + subnetId);
+ boolean match = VpnUtil.isIpInSubnet(ipAddress, subOpEntry.getSubnetCidr());
+ s_logger.trace("SubnetRoutePacketInHandler: Viewing Subnet " + subnetId + " matching " + match);
+ if (match) {
+ dpnid = subOpEntry.getNhDpnId();
+ return dpnid;
+ }
+ }
+ }
+ }
+ return dpnid;
+ }
+
+ private static String toStringIpAddress(byte[] ipAddress)
+ {
+ String ip = null;
+ if (ipAddress == null) {
+ return ip;
+ }
+
+ try {
+ ip = InetAddress.getByAddress(ipAddress).getHostAddress();
+ } catch(UnknownHostException e) {
+ s_logger.error("SubnetRoutePacketInHandler: Unable to translate byt[] ipAddress to String {}", e);
+ }
+
+ return ip;
+ }
+
+ public void setPacketProcessingService(PacketProcessingService service) {
+ this.packetService = service;
+ }
+
+ private long getDpnIdFromPktRcved(PacketReceived packet) {
+ InstanceIdentifier<?> identifier = packet.getIngress().getValue();
+ NodeId id = identifier.firstKeyOf(Node.class, NodeKey.class).getId();
+ return getDpnIdFromNodeName(id.getValue());
+ }
+
+ private long getDpnIdFromNodeName(String nodeName) {
+ String dpId = nodeName.substring(nodeName.lastIndexOf(":") + 1);
+ return Long.parseLong(dpId);
+ }
+
+ private void sendArpRequest(BigInteger dpnId, long groupId, byte[] abySenderMAC, byte[] abySenderIpAddress,
+ byte[] abyTargetIpAddress) {
+
+ s_logger.info("SubnetRoutePacketInHandler: sendArpRequest dpnId {}, groupId {}, senderIPAddress {}, targetIPAddress {}",
+ dpnId, groupId,
+ toStringIpAddress(abySenderIpAddress),toStringIpAddress(abyTargetIpAddress));
+ if (abySenderIpAddress != null) {
+ byte[] arpPacket;
+ byte[] ethPacket;
+ List<ActionInfo> lstActionInfo;
+ TransmitPacketInput transmitPacketInput;
+
+ arpPacket = createARPPacket(ARP.REQUEST, abySenderMAC, abySenderIpAddress, VpnConstants.MAC_Broadcast,
+ abyTargetIpAddress);
+ ethPacket = createEthernetPacket(abySenderMAC, VpnConstants.EthernetDestination_Broadcast, arpPacket);
+ lstActionInfo = new ArrayList<ActionInfo>();
+ lstActionInfo.add(new ActionInfo(ActionType.group, new String[] { String.valueOf(groupId) }));
+ transmitPacketInput = MDSALUtil.getPacketOutDefault(lstActionInfo, ethPacket, dpnId);
+ packetService.transmitPacket(transmitPacketInput);
+ } else {
+ s_logger.info("SubnetRoutePacketInHandler: Unable to send ARP request because client port has no IP ");
+ }
+ }
+
+ private static byte[] createARPPacket(short opCode, byte[] senderMacAddress, byte[] senderIP, byte[] targetMacAddress,
+ byte[] targetIP) {
+ ARP arp = new ARP();
+ byte[] rawArpPkt = null;
+ try {
+ arp.setHardwareType(ARP.HW_TYPE_ETHERNET);
+ arp.setProtocolType(EtherTypes.IPv4.shortValue());
+ arp.setHardwareAddressLength((byte) 6);
+ arp.setProtocolAddressLength((byte) 4);
+ arp.setOpCode(opCode);
+ arp.setSenderHardwareAddress(senderMacAddress);
+ arp.setSenderProtocolAddress(senderIP);
+ arp.setTargetHardwareAddress(targetMacAddress);
+ arp.setTargetProtocolAddress(targetIP);
+ rawArpPkt = arp.serialize();
+ } catch (Exception ex) {
+ s_logger.error("VPNUtil: Serialized ARP packet with senderIp {} targetIP {} exception ",
+ senderIP, targetIP, ex);
+ }
+
+ return rawArpPkt;
+ }
+
+ private static byte[] createEthernetPacket(byte[] sourceMAC, byte[] targetMAC, byte[] arp) {
+ Ethernet ethernet = new Ethernet();
+ byte[] rawEthPkt = null;
+ try {
+ ethernet.setSourceMACAddress(sourceMAC);
+ ethernet.setDestinationMACAddress(targetMAC);
+ ethernet.setEtherType(EtherTypes.ARP.shortValue());
+ ethernet.setRawPayload(arp);
+ rawEthPkt = ethernet.serialize();
+ } catch (Exception ex) {
+ s_logger.error("VPNUtil: Serialized Ethernet packet with sourceMacAddress {} targetMacAddress {} exception ",
+ sourceMAC, targetMAC, ex);
+ }
+ return rawEthPkt;
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.vpnservice;
+
+import java.math.BigInteger;
+
+public class VpnConstants {
+ public static final String VPN_IDPOOL_NAME = "vpnservices";
+ public static final long VPN_IDPOOL_START = 100L;
+ public static final String VPN_IDPOOL_SIZE = "100000";
+ public static final short DEFAULT_FLOW_PRIORITY = 10;
+ public static final short L3VPN_SERVICE_IDENTIFIER = 2;
+ public static final long INVALID_ID = -1;
+ public static final String SEPARATOR = ".";
+ public static final BigInteger COOKIE_VM_INGRESS_TABLE = new BigInteger("8000001", 16);
+ public static final BigInteger COOKIE_L3_BASE = new BigInteger("8000000", 16);
+ public static final String FLOWID_PREFIX = "L3.";
+ public static final long MIN_WAIT_TIME_IN_MILLISECONDS = 10000;
+ public static final long MAX_WAIT_TIME_IN_MILLISECONDS = 90000;
+ public static final int ELAN_GID_MIN = 200000;
+ public static final short ELAN_SMAC_TABLE = 50;
+ public static final short FIB_TABLE = 21;
+ public static byte[] EthernetDestination_Broadcast = new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+ (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
+ public static byte[] MAC_Broadcast = new byte[] { (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0 };
+
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice;
+
+import org.opendaylight.vpnservice.utilities.InterfaceUtils;
+
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+
+import org.opendaylight.controller.md.sal.binding.api.*;
+import org.opendaylight.vpnservice.mdsalutil.*;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.NeutronRouterDpns;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.NeutronvpnService;
+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.l3vpn.rev130911.PrefixToInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.RouterDpnListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey;
+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.arputil.rev151126.OdlArputilService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpResponseInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpResponseInputBuilder;
+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.vpnservice.fibmanager.rev150330.FibEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+
+import java.math.BigInteger;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.concurrent.*;
+
+import com.google.common.base.Optional;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.NeutronvpnService;
+import org.opendaylight.bgpmanager.api.IBgpManager;
+import org.opendaylight.fibmanager.api.IFibManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
+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.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
+ private ListenerRegistration<DataChangeListener> listenerRegistration, opListenerRegistration;
+ private ConcurrentMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<String, Runnable>();
+ private ExecutorService executorService = Executors.newSingleThreadExecutor();
+ private final DataBroker broker;
+ private final IBgpManager bgpManager;
+ private IFibManager fibManager;
+ private IMdsalApiManager mdsalManager;
+ private OdlInterfaceRpcService interfaceManager;
+ private ItmRpcService itmProvider;
+ private IdManagerService idManager;
+ private OdlArputilService arpManager;
+ private NeutronvpnService neuService;
+ private VpnSubnetRouteHandler vpnSubnetRouteHandler;
+ private InterfaceStateChangeListener interfaceListener;
+ private VpnInterfaceOpListener vpnInterfaceOpListener;
+ private ArpNotificationHandler arpNotificationHandler;
+ protected enum UpdateRouteAction {
+ ADVERTISE_ROUTE, WITHDRAW_ROUTE
+ }
+ /**
+ * Responsible for listening to data change related to VPN Interface
+ * Bind VPN Service on the interface and informs the BGP service
+ *
+ * @param db - dataBroker service reference
+ */
+ public VpnInterfaceManager(final DataBroker db, final IBgpManager bgpManager, NotificationService notificationService) {
+ super(VpnInterface.class);
+ broker = db;
+ this.bgpManager = bgpManager;
+ interfaceListener = new InterfaceStateChangeListener(db, this);
+ vpnInterfaceOpListener = new VpnInterfaceOpListener();
+ arpNotificationHandler = new ArpNotificationHandler(this, broker);
+ notificationService.registerNotificationListener(arpNotificationHandler);
+ vpnSubnetRouteHandler = new VpnSubnetRouteHandler(broker, bgpManager, this);
+ notificationService.registerNotificationListener(vpnSubnetRouteHandler);
+ registerListener(db);
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
+ this.interfaceManager = interfaceManager;
+ interfaceListener.setInterfaceManager(interfaceManager);
+ }
+
+ public void setITMProvider(ItmRpcService itmProvider) {
+ this.itmProvider = itmProvider;
+ }
+
+ public void setFibManager(IFibManager fibManager) {
+ this.fibManager = fibManager;
+ }
+
+ public void setIdManager(IdManagerService idManager) {
+ this.idManager = idManager;
+ vpnSubnetRouteHandler.setIdManager(idManager);
+ }
+
+ public void setArpManager(OdlArputilService arpManager) {
+ this.arpManager = arpManager;
+ }
+
+ public void setNeutronvpnManager(NeutronvpnService neuService) { this.neuService = neuService; }
+
+ public VpnSubnetRouteHandler getVpnSubnetRouteHandler() {
+ return this.vpnSubnetRouteHandler;
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ opListenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ opListenerRegistration = null;
+ }
+ LOG.info("VPN Interface Manager Closed");
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ getWildCardPath(), VpnInterfaceManager.this, DataChangeScope.SUBTREE);
+ opListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), vpnInterfaceOpListener, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ LOG.error("VPN Service DataChange listener registration fail!", e);
+ throw new IllegalStateException("VPN Service registration Listener failed.", e);
+ }
+ }
+
+ private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> getInterfaceListenerPath() {
+ return InstanceIdentifier.create(InterfacesState.class)
+ .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class);
+ }
+
+ @Override
+ protected void add(final InstanceIdentifier<VpnInterface> identifier,
+ final VpnInterface vpnInterface) {
+ LOG.trace("VPN Interface key: {} , value: {}", identifier, vpnInterface );
+ addInterface(identifier, vpnInterface);
+ }
+
+ private void addInterface(final InstanceIdentifier<VpnInterface> identifier,
+ final VpnInterface vpnInterface) {
+ LOG.trace("VPN Interface add event - key: {}, value: {}" ,identifier, vpnInterface );
+ final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
+ String interfaceName = key.getName();
+
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
+ InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
+ if (interfaceState != null) {
+ // Interface state is up
+ processVpnInterfaceUp(InterfaceUtils.getDpIdFromInterface(interfaceState), interfaceName, interfaceState.getIfIndex());
+ } else {
+ LOG.trace("VPN interfaces are not yet operational.");
+ }
+ }
+
+ protected void processVpnInterfaceUp(BigInteger dpId, String interfaceName, int lPortTag) {
+
+ VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(broker, interfaceName);
+ if(vpnInterface == null) {
+ LOG.info("Unable to process add/up for interface {} as it is not configured", interfaceName);
+ return;
+ }
+ String vpnName = vpnInterface.getVpnInstanceName();
+ LOG.info("Binding vpn service to interface {} ", interfaceName);
+ long vpnId = VpnUtil.getVpnId(broker, vpnName);
+ if (vpnId == VpnConstants.INVALID_ID) {
+ LOG.trace("VpnInstance to VPNId mapping is not yet available, bailing out now.");
+ return;
+ }
+ synchronized (interfaceName.intern()) {
+ if (VpnUtil.getOperationalVpnInterface(broker, vpnInterface.getName()) != null) {
+ LOG.trace("VPN Interface already provisioned , bailing out from here.");
+ return;
+ }
+ bindService(dpId, vpnName, interfaceName, lPortTag);
+ updateDpnDbs(dpId, vpnName, interfaceName, true);
+ processVpnInterfaceAdjacencies(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
+ }
+
+ }
+
+ private void updateDpnDbs(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
+ long vpnId = VpnUtil.getVpnId(broker, vpnName);
+ if (dpId == null) {
+ dpId = InterfaceUtils.getDpnForInterface(interfaceManager, interfaceName);
+ }
+ if(!dpId.equals(BigInteger.ZERO)) {
+ if(add)
+ updateMappingDbs(vpnId, dpId, interfaceName, vpnName);
+ else
+ removeFromMappingDbs(vpnId, dpId, interfaceName, vpnName);
+ }
+
+ }
+
+ private void bindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName, int lPortTag) {
+ int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
+ long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
+
+ int instructionKey = 0;
+ List<Instruction> instructions = new ArrayList<Instruction>();
+
+ instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID, ++instructionKey));
+ instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.L3_FIB_TABLE, ++instructionKey));
+
+ BoundServices
+ serviceInfo =
+ InterfaceUtils.getBoundServices(String.format("%s.%s.%s", "vpn",vpnInstanceName, vpnInterfaceName),
+ VpnConstants.L3VPN_SERVICE_IDENTIFIER, priority,
+ VpnConstants.COOKIE_VM_INGRESS_TABLE, instructions);
+ VpnUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
+ InterfaceUtils.buildServiceId(vpnInterfaceName, VpnConstants.L3VPN_SERVICE_IDENTIFIER), serviceInfo);
+ makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
+ vpnId, ArpReplyOrRequest.REQUEST, NwConstants.ADD_FLOW);
+ makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
+ vpnId, ArpReplyOrRequest.REPLY, NwConstants.ADD_FLOW);
+
+ }
+
+ private void processVpnInterfaceAdjacencies(BigInteger dpnId, final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
+ String intfName = intf.getName();
+
+ synchronized (intfName) {
+ // Read NextHops
+ InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
+ Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, path);
+
+ if (adjacencies.isPresent()) {
+ List<Adjacency> nextHops = adjacencies.get().getAdjacency();
+ List<Adjacency> value = new ArrayList<>();
+
+ // Get the rd of the vpn instance
+ String rd = getRouteDistinguisher(intf.getVpnInstanceName());
+
+ String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
+ if (nextHopIp == null){
+ LOG.error("NextHop for interface {} is null", intfName);
+ }
+
+ LOG.trace("NextHops are {}", nextHops);
+ for (Adjacency nextHop : nextHops) {
+ String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
+ long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, VpnUtil
+ .getNextHopLabelKey((rd == null) ? intf.getVpnInstanceName() : rd, prefix));
+ String adjNextHop = nextHop.getNextHopIp();
+ value.add(new AdjacencyBuilder(nextHop).setLabel(label).setNextHopIp((adjNextHop != null && !adjNextHop.isEmpty()) ? adjNextHop : nextHopIp)
+ .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
+ if(nextHop.getMacAddress() != null && !nextHop.getMacAddress().isEmpty()) {
+ VpnUtil.syncUpdate(
+ broker,
+ LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getPrefixToInterfaceIdentifier(
+ VpnUtil.getVpnId(broker, intf.getVpnInstanceName()), prefix),
+ VpnUtil.getPrefixToInterface(dpnId, intf.getName(), prefix));
+ } else {
+ //Extra route adjacency
+ VpnUtil.syncUpdate(
+ broker,
+ LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnToExtrarouteIdentifier(
+ (rd != null) ? rd : intf.getVpnInstanceName(), nextHop.getIpAddress()),
+ VpnUtil.getVpnToExtraroute(nextHop.getIpAddress(), nextHop.getNextHopIp()));
+
+ }
+ }
+
+ Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
+ VpnInterface opInterface = VpnUtil.getVpnInterface(intfName, intf.getVpnInstanceName(), aug);
+ InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(intfName);
+ VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface);
+ for (Adjacency nextHop : aug.getAdjacency()) {
+ long label = nextHop.getLabel();
+ //String adjNextHop = nextHop.getNextHopIp();
+ if (rd != null) {
+ addPrefixToBGP(rd, nextHop.getIpAddress(),
+ nextHopIp, label);
+ } else {
+ // ### add FIB route directly
+ addFibEntryToDS(intf.getVpnInstanceName(), nextHop.getIpAddress(),
+ nextHopIp, (int) label);
+ }
+ }
+ }
+ }
+ }
+
+ private void makeArpFlow(BigInteger dpId,short sIndex, int lPortTag, String vpnInterfaceName,
+ long vpnId, ArpReplyOrRequest replyOrRequest, int addOrRemoveFlow){
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lPortTag, ++sIndex, BigInteger.valueOf(vpnId));
+ BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
+ MetaDataUtil.METADATA_MASK_LPORT_TAG, MetaDataUtil.METADATA_MASK_VRFID);
+
+ // Matching Arp reply flows
+ matches.add(new MatchInfo(MatchFieldType.eth_type, new long[] { NwConstants.ETHTYPE_ARP }));
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ metadata, metadataMask }));
+
+ matches.add(new MatchInfo(MatchFieldType.arp_op, new long[] { replyOrRequest.getArpOperation() }));
+
+ // Instruction to punt to controller
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+ actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
+ instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
+
+ // Install the flow entry in L3_INTERFACE_TABLE
+ String flowRef = VpnUtil.getFlowRef(dpId, NwConstants.L3_INTERFACE_TABLE,
+ NwConstants.ETHTYPE_ARP, lPortTag, replyOrRequest.getArpOperation());
+ FlowEntity flowEntity;
+ flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_INTERFACE_TABLE, flowRef,
+ NwConstants.DEFAULT_ARP_FLOW_PRIORITY, replyOrRequest.getName(), 0, 0,
+ VpnUtil.getCookieArpFlow(lPortTag), matches, instructions);
+
+ if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
+ LOG.debug("Creating ARP Flow for interface {}",vpnInterfaceName);
+ mdsalManager.installFlow(flowEntity);
+ } else {
+ LOG.debug("Deleting ARP Flow for interface {}",vpnInterfaceName);
+ mdsalManager.removeFlow(flowEntity);
+ }
+ }
+
+ private String getRouteDistinguisher(String vpnName) {
+ InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
+ .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
+ Optional<VpnInstance> vpnInstance = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
+ String rd = "";
+ if(vpnInstance.isPresent()) {
+ VpnInstance instance = vpnInstance.get();
+ VpnAfConfig config = instance.getIpv4Family();
+ rd = config.getRouteDistinguisher();
+ }
+ return rd;
+ }
+
+ private synchronized void updateMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
+ String routeDistinguisher = getRouteDistinguisher(vpnName);
+ String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
+ InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
+ Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
+ vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
+
+ if (dpnInVpn.isPresent()) {
+ VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id.child(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance
+ .op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
+ new VpnInterfacesKey(intfName)), vpnInterface);
+ } else {
+ VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+ VpnUtil.getVpnInstanceOpDataBuilder(rd, vpnId));
+ VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId);
+ List<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
+ .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = new ArrayList<>();
+ vpnInterfaces.add(vpnInterface);
+ VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id,
+ vpnToDpnList.setVpnInterfaces(vpnInterfaces).build());
+
+ /**
+ * FIXME: DC Gateway tunnel should be built dynamically
+ //this is the first VM in this VPN on the DPN, may be a new DPN has come up,
+ //if tunnel to DC GW does not exist, create it
+ //if(!tunnelExists(dpnID, bgpManager.getDCGWIP()))
+ String dcGW = bgpManager.getDCGwIP();
+ if(dcGW != null && !dcGW.isEmpty())
+ {
+ LOG.debug("Building tunnel from DPN {} to DC GW {}", dpnId, dcGW);
+ itmProvider.buildTunnelFromDPNToDCGW(dpnId, new IpAddress(dcGW.toCharArray()));
+ }*/
+ fibManager.populateFibOnNewDpn(dpnId, vpnId, (rd == null) ? vpnName : rd);
+ }
+ }
+
+ private synchronized void removeFromMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
+ //TODO: Delay 'DPN' removal so that other services can cleanup the entries for this dpn
+ String rd = VpnUtil.getVpnRd(broker, vpnName);
+ InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
+ Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ if (dpnInVpn.isPresent()) {
+ List<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
+ .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
+ org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
+ currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
+
+ if (vpnInterfaces.remove(currVpnInterface)) {
+ if (vpnInterfaces.isEmpty()) {
+ VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id, VpnUtil.DEFAULT_CALLBACK);
+ fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
+ } else {
+ VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id.child(
+ org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
+ .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
+ new VpnInterfacesKey(intfName)), VpnUtil.DEFAULT_CALLBACK);
+ }
+ }
+ }
+ }
+
+ private void addPrefixToBGP(String rd, String prefix, String nextHopIp, long label) {
+ try {
+ bgpManager.addPrefix(rd, prefix, nextHopIp, (int)label);
+ } catch(Exception e) {
+ LOG.error("Add prefix failed", e);
+ }
+ }
+
+
+ private InstanceIdentifier<VpnInterface> getWildCardPath() {
+ return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);
+ }
+
+ @Override
+ protected void remove( InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
+ LOG.trace("Remove event - key: {}, value: {}" ,identifier, vpnInterface );
+ final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
+ String interfaceName = key.getName();
+
+ InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
+ Optional<VpnInterface> existingVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
+ InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
+
+ if (existingVpnInterface.isPresent() && interfaceState != null) {
+ processVpnInterfaceDown(InterfaceUtils.getDpIdFromInterface(interfaceState), interfaceName, interfaceState.getIfIndex(), false);
+ } else {
+ LOG.warn("VPN interface {} was unavailable in operational data store to handle remove event", interfaceName);
+ }
+ }
+
+ protected void processVpnInterfaceDown(BigInteger dpId, String interfaceName, int lPortTag, boolean isInterfaceStateDown) {
+ VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(broker, interfaceName);
+ if(vpnInterface == null) {
+ LOG.info("Unable to process delete/down for interface {} as it is not available in operational data store", interfaceName);
+ return;
+ }
+ String vpnName = vpnInterface.getVpnInstanceName();
+ InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
+
+ synchronized (interfaceName.intern()) {
+ removeAdjacenciesFromVpn(identifier, vpnInterface);
+ LOG.info("Unbinding vpn service from interface {} ", interfaceName);
+ unbindService(dpId, vpnName, interfaceName, lPortTag, isInterfaceStateDown);
+
+ //wait till DCN for removal of vpn interface in operational DS arrives
+ Runnable notifyTask = new VpnNotifyTask();
+ synchronized (interfaceName.intern()) {
+ vpnIntfMap.put(interfaceName, notifyTask);
+ synchronized (notifyTask) {
+ try {
+ notifyTask.wait(VpnConstants.MIN_WAIT_TIME_IN_MILLISECONDS);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ }
+ }
+
+ private void removeAdjacenciesFromVpn(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
+ //Read NextHops
+ InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
+ Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
+
+ String rd = VpnUtil.getVpnRd(broker, intf.getVpnInstanceName());
+ LOG.trace("removeAdjacenciesFromVpn: For interface {} RD recovered for vpn {} as rd {}", intf.getName(),
+ intf.getVpnInstanceName(), rd);
+ if (adjacencies.isPresent()) {
+ List<Adjacency> nextHops = adjacencies.get().getAdjacency();
+
+ if (!nextHops.isEmpty()) {
+ LOG.trace("NextHops are " + nextHops);
+ for (Adjacency nextHop : nextHops) {
+ // Commenting the release of ID here as it will be released by FIB
+ /* VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME,
+ VpnUtil.getNextHopLabelKey(rd, nextHop.getIpAddress()));
+ VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getPrefixToInterfaceIdentifier(
+ VpnUtil.getVpnId(broker, intf.getVpnInstanceName()),
+ nextHop.getIpAddress()),
+ VpnUtil.DEFAULT_CALLBACK);*/
+ if (rd.equals(intf.getVpnInstanceName())) {
+ //this is an internal vpn - the rd is assigned to the vpn instance name;
+ //remove from FIB directly
+ removeFibEntryFromDS(intf.getVpnInstanceName(), nextHop.getIpAddress());
+ } else {
+ removePrefixFromBGP(rd, nextHop.getIpAddress());
+ }
+ }
+ }
+ }
+ }
+
+
+ private void unbindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName,
+ int lPortTag, boolean isInterfaceStateDown) {
+ if (!isInterfaceStateDown) {
+ VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION,
+ InterfaceUtils.buildServiceId(vpnInterfaceName,
+ VpnConstants.L3VPN_SERVICE_IDENTIFIER),
+ VpnUtil.DEFAULT_CALLBACK);
+ }
+ long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
+ makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
+ vpnId, ArpReplyOrRequest.REQUEST, NwConstants.DEL_FLOW);
+ makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
+ vpnId, ArpReplyOrRequest.REPLY, NwConstants.DEL_FLOW);
+ }
+
+
+ private void removePrefixFromBGP(String rd, String prefix) {
+ try {
+ bgpManager.deletePrefix(rd, prefix);
+ } catch(Exception e) {
+ LOG.error("Delete prefix failed", e);
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<VpnInterface> identifier, VpnInterface original, VpnInterface update) {
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Updating VPN Interface : key " + identifier + ", original value=" + original + ", update " +
+ "value=" + update);
+ }
+ String oldVpnName = original.getVpnInstanceName();
+ String newVpnName = update.getVpnInstanceName();
+ List<Adjacency> oldAdjs = original.getAugmentation(Adjacencies.class).getAdjacency();
+ List<Adjacency> newAdjs = update.getAugmentation(Adjacencies.class).getAdjacency();
+ if (oldAdjs == null) {
+ oldAdjs = new ArrayList<>();
+ }
+ if (newAdjs == null) {
+ newAdjs = new ArrayList<>();
+ }
+ //handles switching between <internal VPN - external VPN>
+ if (!oldVpnName.equals(newVpnName)) {
+ remove(identifier, original);
+ add(identifier, update);
+ }
+ //handle both addition and removal of adjacencies
+ //currently, new adjacency may be an extra route
+ if (!oldAdjs.equals(newAdjs)) {
+ for (Adjacency adj : newAdjs) {
+ if (oldAdjs.contains(adj)) {
+ oldAdjs.remove(adj);
+ } else {
+ // add new adjacency - right now only extra route will hit this path
+ addNewAdjToVpnInterface(identifier, adj);
+ }
+ }
+ for (Adjacency adj : oldAdjs) {
+ delAdjFromVpnInterface(identifier, adj);
+ }
+ }
+ }
+
+ public void processArpRequest(IpAddress srcIP, PhysAddress srcMac, IpAddress targetIP, String srcInterface){
+ SendArpResponseInput input = new SendArpResponseInputBuilder().setInterface(srcInterface)
+ .setIpaddress(srcIP).setSrcIpAddress(targetIP).setMacaddress(srcMac).build();
+ final String msgFormat = String.format("Send ARP Response on interface %s to destination %s", srcInterface, srcIP);
+ Future<RpcResult<Void>> future = arpManager.sendArpResponse(input);
+ Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), new FutureCallback<RpcResult<Void>>() {
+ @Override
+ public void onFailure(Throwable error) {
+ LOG.error("Error - {}", msgFormat, error);
+ }
+
+ @Override
+ public void onSuccess(RpcResult<Void> result) {
+ if(!result.isSuccessful()) {
+ LOG.warn("Rpc call to {} failed", msgFormat, getErrorText(result.getErrors()));
+ } else {
+ LOG.debug("Successful RPC Result - {}", msgFormat);
+ }
+ }
+ });
+ }
+
+ private String getErrorText(Collection<RpcError> errors) {
+ StringBuilder errorText = new StringBuilder();
+ for(RpcError error : errors) {
+ errorText.append(",").append(error.getErrorType()).append("-")
+ .append(error.getMessage());
+ }
+ return errorText.toString();
+ }
+
+ private String getTunnelInterfaceFlowRef(BigInteger dpnId, short tableId, String ifName) {
+ return new StringBuilder().append(dpnId).append(tableId).append(ifName).toString();
+ }
+
+
+
+ public synchronized void addFibEntryToDS(String rd, String prefix,
+ String nexthop, int label) {
+
+ VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).
+ setNextHopAddress(nexthop).setLabel((long)label).build();
+ LOG.debug("Created vrfEntry for {} nexthop {} label {}", prefix, nexthop, label);
+
+ List<VrfEntry> vrfEntryList = new ArrayList<VrfEntry>();
+ vrfEntryList.add(vrfEntry);
+
+ InstanceIdentifierBuilder<VrfTables> idBuilder =
+ InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
+ InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
+
+ VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
+ setVrfEntry(vrfEntryList).build();
+
+ VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
+ }
+
+ public synchronized void removeFibEntryFromDS(String rd, String prefix) {
+
+ LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {}", prefix, rd);
+
+ InstanceIdentifierBuilder<VrfEntry> idBuilder =
+ InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(VrfEntry.class, new VrfEntryKey(prefix));
+ InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
+ VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, VpnUtil.DEFAULT_CALLBACK);
+
+ }
+
+ public synchronized void removeVrfFromDS(String rd) {
+ LOG.debug("Removing vrf table for rd {}", rd);
+
+ InstanceIdentifierBuilder<VrfTables> idBuilder =
+ InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
+ InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
+
+ VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, VpnUtil.DEFAULT_CALLBACK);
+
+ }
+
+ protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj) {
+
+ Optional<VpnInterface> optVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
+
+ if (optVpnInterface.isPresent()) {
+ VpnInterface currVpnIntf = optVpnInterface.get();
+ String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
+ String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
+ InstanceIdentifier<Adjacencies> adjPath = identifier.augmentation(Adjacencies.class);
+ Optional<Adjacencies> optAdjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, adjPath);
+ long label =
+ VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
+ VpnUtil.getNextHopLabelKey((rd != null) ? rd : currVpnIntf.getVpnInstanceName(), prefix));
+
+ List<Adjacency> adjacencies;
+ if (optAdjacencies.isPresent()) {
+ adjacencies = optAdjacencies.get().getAdjacency();
+ } else {
+ //This code will not be hit since VM adjacency will always be there
+ adjacencies = new ArrayList<>();
+ }
+
+ adjacencies.add(new AdjacencyBuilder(adj).setLabel(label).setNextHopIp(adj.getNextHopIp())
+ .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
+
+ Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
+ VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(), aug);
+
+ VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
+ addExtraRoute(adj.getIpAddress(), adj.getNextHopIp(), rd, currVpnIntf.getVpnInstanceName(), (int) label, currVpnIntf.getName());
+
+ }
+
+ }
+
+ protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj) {
+ Optional<VpnInterface> optVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
+
+ if (optVpnInterface.isPresent()) {
+ VpnInterface currVpnIntf = optVpnInterface.get();
+
+ InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
+ Optional<Adjacencies> optAdjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
+ if (optAdjacencies.isPresent()) {
+ List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
+
+ if (!adjacencies.isEmpty()) {
+ String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
+ LOG.trace("Adjacencies are " + adjacencies);
+ Iterator<Adjacency> adjIt = adjacencies.iterator();
+ while (adjIt.hasNext()) {
+ Adjacency adjElem = adjIt.next();
+ if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
+ // Commenting the release of ID here as it will be released by FIB
+ /* VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME,
+ VpnUtil.getNextHopLabelKey(rd, adj.getIpAddress()));*/
+ adjIt.remove();
+
+ Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
+ VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(),
+ currVpnIntf.getVpnInstanceName(),
+ aug);
+
+ VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
+
+ delExtraRoute(adj.getIpAddress(), rd, currVpnIntf.getVpnInstanceName());
+ break;
+ }
+
+ }
+ }
+ }
+ }
+
+ }
+
+ protected void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label, String intfName) {
+
+ //add extra route to vpn mapping; advertise with nexthop as tunnel ip
+ VpnUtil.syncUpdate(
+ broker,
+ LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnToExtrarouteIdentifier(
+ (rd != null) ? rd : routerID, destination),
+ VpnUtil.getVpnToExtraroute(destination, nextHop));
+
+ if (intfName != null && !intfName.isEmpty()) {
+ BigInteger dpnId = InterfaceUtils.getDpnForInterface(interfaceManager, intfName);
+ String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
+ if (nextHopIp == null || nextHopIp.isEmpty()) {
+ LOG.warn("NextHop for interface {} is null / empty. Failed advertising extra route for prefix {}", intfName, destination);
+ }
+ nextHop = nextHopIp;
+ }
+ if (rd != null) {
+ addPrefixToBGP(rd, destination, nextHop, label);
+ } else {
+ // ### add FIB route directly
+ addFibEntryToDS(routerID, destination, nextHop, label);
+ }
+ }
+
+ protected void delExtraRoute(String destination, String rd, String routerID) {
+ if (rd != null) {
+ removePrefixFromBGP(rd, destination);
+ } else {
+ // ### add FIB route directly
+ removeFibEntryFromDS(routerID, destination);
+ }
+ }
+
+ class VpnInterfaceOpListener extends org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener<VpnInterface> {
+
+ public VpnInterfaceOpListener() {
+ super(VpnInterface.class);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<VpnInterface> identifier, VpnInterface del) {
+ final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
+ String interfaceName = key.getName();
+ String vpnName = del.getVpnInstanceName();
+
+ LOG.trace("VpnInterfaceOpListener removed: interface name {} vpnName {}", interfaceName, vpnName);
+ //decrement the vpn interface count in Vpn Instance Op Data
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
+ id = VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnName);
+ Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
+ = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
+
+ if (vpnInstance.isPresent()) {
+ String rd = null;
+ rd = vpnInstance.get().getVrfId();
+ //String rd = getRouteDistinguisher(del.getVpnInstanceName());
+
+ VpnInstanceOpDataEntry vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
+ LOG.trace("VpnInterfaceOpListener removed: interface name {} rd {} vpnName {} in Vpn Op Instance {}",
+ interfaceName, rd, vpnName, vpnInstOp);
+
+ if (vpnInstOp != null) {
+ // Vpn Interface removed => No more adjacencies from it.
+ // Hence clean up interface from vpn-dpn-interface list.
+ Adjacency adjacency = del.getAugmentation(Adjacencies.class).getAdjacency().get(0);
+ Optional<Prefixes> prefixToInterface = Optional.absent();
+ prefixToInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
+ VpnUtil.getIpPrefix(adjacency.getIpAddress())));
+ if (!prefixToInterface.isPresent()) {
+ prefixToInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
+ VpnUtil.getIpPrefix(adjacency.getNextHopIp())));
+ }
+ if (prefixToInterface.isPresent()) {
+ VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
+ prefixToInterface.get().getIpAddress()),
+ VpnUtil.DEFAULT_CALLBACK);
+ updateDpnDbs(prefixToInterface.get().getDpnId(), del.getVpnInstanceName(), interfaceName, false);
+ }
+ Long ifCnt = 0L;
+ ifCnt = vpnInstOp.getVpnInterfaceCount();
+ LOG.trace("VpnInterfaceOpListener removed: interface name {} rd {} vpnName {} Intf count {}",
+ interfaceName, rd, vpnName, ifCnt);
+ if ((ifCnt != null) && (ifCnt > 0)) {
+ VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+ VpnUtil.updateIntfCntInVpnInstOpData(ifCnt - 1, rd), VpnUtil.DEFAULT_CALLBACK);
+ }
+ }
+ } else {
+ LOG.error("rd not retrievable as vpninstancetovpnid for vpn {} is absent, trying rd as ", vpnName, vpnName);
+ }
+ notifyTaskIfRequired(interfaceName);
+ }
+
+ private void notifyTaskIfRequired(String intfName) {
+ Runnable notifyTask = vpnIntfMap.remove(intfName);
+ if (notifyTask == null) {
+ return;
+ }
+ executorService.execute(notifyTask);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<VpnInterface> identifier, VpnInterface original, VpnInterface update) {
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<VpnInterface> identifier, VpnInterface add) {
+ final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
+ String interfaceName = key.getName();
+
+ //increment the vpn interface count in Vpn Instance Op Data
+ Long ifCnt = 0L;
+ String rd = getRouteDistinguisher(add.getVpnInstanceName());
+ if(rd == null || rd.isEmpty()) rd = add.getVpnInstanceName();
+ VpnInstanceOpDataEntry vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
+ if(vpnInstOp != null && vpnInstOp.getVpnInterfaceCount() != null) {
+ ifCnt = vpnInstOp.getVpnInterfaceCount();
+ }
+
+ LOG.trace("VpnInterfaceOpListener add: interface name {} rd {} interface count in Vpn Op Instance {}", interfaceName, rd, ifCnt);
+
+ VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+ VpnUtil.updateIntfCntInVpnInstOpData(ifCnt + 1, rd), VpnUtil.DEFAULT_CALLBACK);
+
+
+ }
+ }
+
+ protected void updatePrefixesForDPN(BigInteger dpnId, UpdateRouteAction action) {
+
+ LOG.info("Tunnel event triggered {} for Dpn:{} ", action.name(), dpnId);
+ InstanceIdentifierBuilder<VpnInstances> idBuilder = InstanceIdentifier.builder(VpnInstances.class);
+ InstanceIdentifier<VpnInstances> vpnInstancesId = idBuilder.build();
+ Optional<VpnInstances> vpnInstances = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vpnInstancesId);
+
+ if (vpnInstances.isPresent()) {
+ List<VpnInstance> vpnInstanceList = vpnInstances.get().getVpnInstance();
+ Iterator<VpnInstance> vpnInstIter = vpnInstanceList.iterator();
+ while (vpnInstIter.hasNext()) {
+ VpnInstance vpnInstance = vpnInstIter.next();
+ try {
+ VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
+ String rd = vpnConfig.getRouteDistinguisher();
+ if (rd == null || rd.isEmpty()) {
+ rd = vpnInstance.getVpnInstanceName();
+ }
+ InstanceIdentifier<VpnToDpnList> id =
+ VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
+ Optional<VpnToDpnList> dpnInVpn =
+ VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ if (dpnInVpn.isPresent()) {
+ // if (action == UpdateRouteAction.ADVERTISE_ROUTE) {
+ // fibManager.populateFibOnNewDpn(dpnId, VpnUtil
+ // .getVpnId(broker, vpnInstance.getVpnInstanceName()), rd);
+ // }
+ List<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
+ .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces>
+ vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
+ for (org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
+ .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces vpnInterface : vpnInterfaces) {
+ InstanceIdentifier<VpnInterface> vpnIntfId =
+ VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getInterfaceName());
+ InstanceIdentifier<Adjacencies> path =
+ vpnIntfId.augmentation(Adjacencies.class);
+ Optional<Adjacencies> adjacencies =
+ VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
+
+ if (adjacencies.isPresent()) {
+ List<Adjacency> adjacencyList = adjacencies.get().getAdjacency();
+ Iterator<Adjacency> adjacencyIterator = adjacencyList.iterator();
+
+ while (adjacencyIterator.hasNext()) {
+ Adjacency adjacency = adjacencyIterator.next();
+ try {
+ if (action == UpdateRouteAction.ADVERTISE_ROUTE)
+ bgpManager.addPrefix(rd, adjacency.getIpAddress(),
+ adjacency.getNextHopIp(),
+ adjacency.getLabel().intValue());
+ else if (action == UpdateRouteAction.WITHDRAW_ROUTE)
+ bgpManager.deletePrefix(rd, adjacency.getIpAddress());
+ } catch (Exception e) {
+ LOG.error("Exception when updating prefix {} in vrf {} to BGP",
+ adjacency.getIpAddress(), rd);
+ }
+ }
+ }
+
+ }
+ // if (action == UpdateRouteAction.WITHDRAW_ROUTE) {
+ // fibManager.cleanUpDpnForVpn(dpnId, VpnUtil.getVpnId(broker, vpnInstance.getVpnInstanceName()), rd);
+ // }
+ }
+ } catch (Exception e) {
+ LOG.error("updatePrefixesForDPN {} in vpn {} failed", dpnId, vpnInstance.getVpnInstanceName(), e);
+ }
+ }
+ }
+ }
+
+ InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
+ return InstanceIdentifier.builder(NeutronRouterDpns.class)
+ .child(RouterDpnList.class, new RouterDpnListKey(routerName))
+ .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
+ }
+
+ InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
+ return InstanceIdentifier.builder(NeutronRouterDpns.class)
+ .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
+ }
+
+ protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName) {
+ BigInteger dpId = InterfaceUtils.getDpnForInterface(interfaceManager, vpnInterfaceName);
+ if(dpId.equals(BigInteger.ZERO)) {
+ LOG.warn("Could not retrieve dp id for interface {} to handle router {} association model", vpnInterfaceName, routerName);
+ return;
+ }
+ InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
+
+ Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(broker, LogicalDatastoreType
+ .CONFIGURATION, routerDpnListIdentifier);
+ RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
+ if (optionalRouterDpnList.isPresent()) {
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, routerDpnListIdentifier.child(
+ RouterInterfaces.class, new RouterInterfacesKey(vpnInterfaceName)), routerInterface);
+ } else {
+ MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION,
+ getRouterId(routerName),
+ new RouterDpnListBuilder().setRouterId(routerName).build());
+ //VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId);
+ DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
+ List<RouterInterfaces> routerInterfaces = new ArrayList<>();
+ routerInterfaces.add(routerInterface);
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, routerDpnListIdentifier,
+ dpnVpnList.setRouterInterfaces(routerInterfaces).build());
+ }
+ }
+
+ protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName) {
+ BigInteger dpId = InterfaceUtils.getDpnForInterface(interfaceManager, vpnInterfaceName);
+ if(dpId.equals(BigInteger.ZERO)) {
+ LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
+ return;
+ }
+ InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
+ Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(broker, LogicalDatastoreType
+ .CONFIGURATION, routerDpnListIdentifier);
+ if (optionalRouterDpnList.isPresent()) {
+ List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
+ RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
+
+ if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
+ if (routerInterfaces.isEmpty()) {
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, routerDpnListIdentifier);
+ } else {
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, routerDpnListIdentifier.child(
+ RouterInterfaces.class,
+ new RouterInterfacesKey(vpnInterfaceName)));
+ }
+ }
+ }
+ }
+
+ protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,BigInteger dpId) {
+ if(dpId.equals(BigInteger.ZERO)) {
+ LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
+ return;
+ }
+ InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
+ Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(broker, LogicalDatastoreType
+ .CONFIGURATION, routerDpnListIdentifier);
+ if (optionalRouterDpnList.isPresent()) {
+ List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
+ RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
+
+ if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
+ if (routerInterfaces.isEmpty()) {
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, routerDpnListIdentifier);
+ } else {
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, routerDpnListIdentifier.child(
+ RouterInterfaces.class,
+ new RouterInterfacesKey(vpnInterfaceName)));
+ }
+ }
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.*;
+
+import com.google.common.util.concurrent.CheckedFuture;
+import org.opendaylight.bgpmanager.api.IBgpManager;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.NotificationService;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceToVpnId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceToVpnIdBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnRouteList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
+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.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceOpDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.FibEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+
+public class VpnManager extends AbstractDataChangeListener<VpnInstance> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(VpnManager.class);
+ private ListenerRegistration<DataChangeListener> listenerRegistration, fibListenerRegistration, opListenerRegistration;
+ private ConcurrentMap<String, Runnable> vpnOpMap = new ConcurrentHashMap<String, Runnable>();
+ private ExecutorService executorService = Executors.newSingleThreadExecutor();
+ private final DataBroker broker;
+ private final IBgpManager bgpManager;
+ private IdManagerService idManager;
+ private VpnInterfaceManager vpnInterfaceManager;
+ private final FibEntriesListener fibListener;
+ private final VpnInstanceOpListener vpnInstOpListener;
+ private NotificationService notificationService;
+
+ private static final FutureCallback<Void> DEFAULT_CALLBACK =
+ new FutureCallback<Void>() {
+ public void onSuccess(Void result) {
+ LOG.debug("Success in Datastore operation");
+ }
+
+ public void onFailure(Throwable error) {
+ LOG.error("Error in Datastore operation", error);
+ };
+ };
+
+ /**
+ * Listens for data change related to VPN Instance
+ * Informs the BGP about VRF information
+ *
+ * @param db - dataBroker reference
+ */
+ public VpnManager(final DataBroker db, final IBgpManager bgpManager) {
+ super(VpnInstance.class);
+ broker = db;
+ this.bgpManager = bgpManager;
+ this.fibListener = new FibEntriesListener();
+ this.vpnInstOpListener = new VpnInstanceOpListener();
+ registerListener(db);
+ }
+
+ private void registerListener(final DataBroker db) {
+ try {
+ listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ getWildCardPath(), VpnManager.this, DataChangeScope.SUBTREE);
+ fibListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getFibEntryListenerPath(), fibListener, DataChangeScope.BASE);
+ opListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getVpnInstanceOpListenerPath(), vpnInstOpListener, DataChangeScope.SUBTREE);
+
+ } catch (final Exception e) {
+ LOG.error("VPN Service DataChange listener registration fail !", e);
+ throw new IllegalStateException("VPN Service registration Listener failed.", e);
+ }
+ }
+
+ public void setIdManager(IdManagerService idManager) {
+ this.idManager = idManager;
+ }
+
+ public void setVpnInterfaceManager(VpnInterfaceManager vpnInterfaceManager) {
+ this.vpnInterfaceManager = vpnInterfaceManager;
+ }
+
+ private void waitForOpRemoval(String id, long timeout) {
+ //wait till DCN for update on VPN Instance Op Data signals that vpn interfaces linked to this vpn instance is zero
+ Runnable notifyTask = new VpnNotifyTask();
+ synchronized (id.intern()) {
+ try {
+ vpnOpMap.put(id, notifyTask);
+ synchronized (notifyTask) {
+ try {
+ notifyTask.wait(timeout);
+ } catch (InterruptedException e) {
+ }
+ }
+ } finally {
+ vpnOpMap.remove(id);
+ }
+ }
+
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<VpnInstance> identifier, VpnInstance del) {
+ LOG.trace("Remove VPN event key: {}, value: {}", identifier, del);
+ String vpnName = del.getVpnInstanceName();
+ String rd = del.getIpv4Family().getRouteDistinguisher();
+ long vpnId = VpnUtil.getVpnId(broker, vpnName);
+
+ //TODO(vpnteam): Entire code would need refactoring to listen only on the parent object - VPNInstance
+ Optional<VpnInstanceOpDataEntry> vpnOpValue = null;
+ if ((rd != null) && (!rd.isEmpty())) {
+ vpnOpValue = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnInstanceOpDataIdentifier(rd));
+ } else {
+ vpnOpValue = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnInstanceOpDataIdentifier(vpnName));
+ }
+
+ if ((vpnOpValue != null) && (vpnOpValue.isPresent())) {
+ VpnInstanceOpDataEntry vpnOpEntry = null;
+ long timeout = VpnConstants.MIN_WAIT_TIME_IN_MILLISECONDS;
+ Long intfCount = 0L;
+
+ vpnOpEntry = vpnOpValue.get();
+ intfCount = vpnOpEntry.getVpnInterfaceCount();
+ if (intfCount != null && intfCount > 0) {
+ // Minimum wait time of 10 seconds for one VPN Interface clearance (inclusive of full trace on)
+ timeout = intfCount * 10000;
+ // Maximum wait time of 90 seconds for all VPN Interfaces clearance (inclusive of full trace on)
+ if (timeout > VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS) {
+ timeout = VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS;
+ }
+ LOG.trace("VPNInstance removal count of interface at {} for for rd {}, vpnname {}",
+ intfCount, rd, vpnName);
+ }
+ LOG.trace("VPNInstance removal thread waiting for {} seconds for rd {}, vpnname {}",
+ (timeout/1000), rd, vpnName);
+
+ if ((rd != null) && (!rd.isEmpty())) {
+ waitForOpRemoval(rd, timeout);
+ } else {
+ waitForOpRemoval(vpnName, timeout);
+ }
+
+ LOG.trace("Returned out of waiting for Op Data removal for rd {}, vpnname {}", rd, vpnName);
+ }
+ // Clean up VpnInstanceToVpnId from Config DS
+ VpnUtil.removeVpnInstanceToVpnId(broker, vpnName);
+ LOG.trace("Removed vpnIdentifier for rd{} vpnname {}", rd, vpnName);
+ if (rd != null) {
+ try {
+ bgpManager.deleteVrf(rd);
+ } catch (Exception e) {
+ LOG.error("Exception when removing VRF from BGP for RD {} in VPN {} exception " + e, rd, vpnName);
+ }
+
+ // Clean up VPNExtraRoutes Operational DS
+ VpnUtil.removeVpnExtraRouteForVpn(broker, rd);
+
+ // Clean up VPNInstanceOpDataEntry
+ VpnUtil.removeVpnOpInstance(broker, rd);
+ } else {
+ // Clean up FIB Entries Config DS
+ VpnUtil.removeVrfTableForVpn(broker, vpnName);
+
+ // Clean up VPNExtraRoutes Operational DS
+ VpnUtil.removeVpnExtraRouteForVpn(broker, vpnName);
+
+ // Clean up VPNInstanceOpDataEntry
+ VpnUtil.removeVpnOpInstance(broker, vpnName);
+ }
+
+ // Clean up PrefixToInterface Operational DS
+ VpnUtil.removePrefixToInterfaceForVpnId(broker, vpnId);
+
+ // Clean up L3NextHop Operational DS
+ VpnUtil.removeL3nexthopForVpnId(broker, vpnId);
+
+ // Release the ID used for this VPN back to IdManager
+
+ VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME, vpnName);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<VpnInstance> identifier,
+ VpnInstance original, VpnInstance update) {
+ LOG.trace("Update VPN event key: {}, value: {}", identifier, update);
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<VpnInstance> identifier,
+ VpnInstance value) {
+ LOG.trace("Add VPN event key: {}, value: {}", identifier, value);
+ VpnAfConfig config = value.getIpv4Family();
+ String rd = config.getRouteDistinguisher();
+
+ long vpnId = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, value.getVpnInstanceName());
+ LOG.trace("VPN instance to ID generated.");
+ org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
+ vpnInstanceToVpnId = VpnUtil.getVpnInstanceToVpnId(value.getVpnInstanceName(), vpnId,
+ (rd != null) ? rd : value.getVpnInstanceName());
+
+ syncWrite(LogicalDatastoreType.CONFIGURATION,
+ VpnUtil.getVpnInstanceToVpnIdIdentifier(value.getVpnInstanceName()),
+ vpnInstanceToVpnId, DEFAULT_CALLBACK);
+
+
+ if(rd == null) {
+ VpnInstanceOpDataEntryBuilder builder = new VpnInstanceOpDataEntryBuilder();
+ builder.setVrfId(value.getVpnInstanceName()).setVpnId(vpnId);
+ builder.setVpnInterfaceCount(0L);
+ syncWrite(LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnInstanceOpDataIdentifier(value.getVpnInstanceName()),
+ builder.build(), DEFAULT_CALLBACK);
+
+ } else {
+ VpnInstanceOpDataEntryBuilder builder = new VpnInstanceOpDataEntryBuilder();
+ builder.setVrfId(rd).setVpnId(vpnId);
+ builder.setVpnInterfaceCount(0L);
+ syncWrite(LogicalDatastoreType.OPERATIONAL,
+ VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+ builder.build(), DEFAULT_CALLBACK);
+
+ List<VpnTarget> vpnTargetList = config.getVpnTargets().getVpnTarget();
+
+ List<String> ertList = new ArrayList<String>();
+ List<String> irtList = new ArrayList<String>();
+
+ for (VpnTarget vpnTarget : vpnTargetList) {
+ if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ExportExtcommunity) {
+ ertList.add(vpnTarget.getVrfRTValue());
+ }
+ if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.ImportExtcommunity) {
+ irtList.add(vpnTarget.getVrfRTValue());
+ }
+ if (vpnTarget.getVrfRTType() == VpnTarget.VrfRTType.Both) {
+ ertList.add(vpnTarget.getVrfRTValue());
+ irtList.add(vpnTarget.getVrfRTValue());
+ }
+ }
+
+ try {
+ bgpManager.addVrf(rd, irtList, ertList);
+ } catch(Exception e) {
+ LOG.error("Exception when adding VRF to BGP", e);
+ }
+ }
+ //Try to add up vpn Interfaces if already in Operational Datastore
+ InstanceIdentifier<VpnInterfaces> vpnInterfacesId = InstanceIdentifier.builder(VpnInterfaces.class).build();
+ Optional<VpnInterfaces> optionalVpnInterfaces = read(LogicalDatastoreType.CONFIGURATION, vpnInterfacesId);
+
+ if(optionalVpnInterfaces.isPresent()) {
+ List<VpnInterface> vpnInterfaces = optionalVpnInterfaces.get().getVpnInterface();
+ for(VpnInterface vpnInterface : vpnInterfaces) {
+ if(vpnInterface.getVpnInstanceName().equals(value.getVpnInstanceName())) {
+ LOG.debug("VpnInterface {} will be added from VPN {}", vpnInterface.getName(), value.getVpnInstanceName());
+ vpnInterfaceManager.add(
+ VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
+
+ }
+ }
+ }
+ }
+
+ private InstanceIdentifier<?> getWildCardPath() {
+ return InstanceIdentifier.create(VpnInstances.class).child(VpnInstance.class);
+ }
+
+ private InstanceIdentifier<?> getFibEntryListenerPath() {
+ return InstanceIdentifier.create(FibEntries.class).child(VrfTables.class)
+ .child(VrfEntry.class);
+ }
+
+ private InstanceIdentifier<?> getVpnInstanceOpListenerPath() {
+ return InstanceIdentifier.create(VpnInstanceOpData.class).child(VpnInstanceOpDataEntry.class);
+
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up Vpn DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ if (fibListenerRegistration != null) {
+ try {
+ fibListenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up Fib entries DataChangeListener.", e);
+ }
+ fibListenerRegistration = null;
+ }
+ if (opListenerRegistration != null) {
+ try {
+ opListenerRegistration.close();
+ } catch (final Exception e) {
+ LOG.error("Error when cleaning up VPN Instance Operational entries DataChangeListener.", e);
+ }
+ opListenerRegistration = null;
+ }
+
+ LOG.trace("VPN Manager Closed");
+ }
+
+ private <T extends DataObject> Optional<T> read(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;
+ }
+
+ private <T extends DataObject> void asyncWrite(LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.put(datastoreType, path, data, true);
+ Futures.addCallback(tx.submit(), callback);
+ }
+
+ private <T extends DataObject> void syncWrite(LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.put(datastoreType, path, data, true);
+ CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+ try {
+ futures.get();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Error writing VPN instance to ID info to datastore (path, data) : ({}, {})", path, data);
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+
+ protected VpnInstanceOpDataEntry getVpnInstanceOpData(String rd) {
+ InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
+ Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = read(LogicalDatastoreType.OPERATIONAL, id);
+ if(vpnInstanceOpData.isPresent()) {
+ return vpnInstanceOpData.get();
+ }
+ return null;
+ }
+
+ private <T extends DataObject> void delete(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.delete(datastoreType, path);
+ Futures.addCallback(tx.submit(), DEFAULT_CALLBACK);
+ }
+
+ private class FibEntriesListener extends AbstractDataChangeListener<VrfEntry> {
+
+ public FibEntriesListener() {
+ super(VrfEntry.class);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<VrfEntry> identifier,
+ VrfEntry del) {
+ LOG.trace("Remove Fib event - Key : {}, value : {} ", identifier, del);
+ final VrfTablesKey key = identifier.firstKeyOf(VrfTables.class, VrfTablesKey.class);
+ String rd = key.getRouteDistinguisher();
+ Long label = del.getLabel();
+ VpnInstanceOpDataEntry vpnInstanceOpData = getVpnInstanceOpData(rd);
+ if(vpnInstanceOpData != null) {
+ List<Long> routeIds = vpnInstanceOpData.getRouteEntryId();
+ if(routeIds == null) {
+ LOG.debug("Fib Route entry is empty.");
+ return;
+ }
+ LOG.debug("Removing label from vpn info - {}", label);
+ routeIds.remove(label);
+ asyncWrite(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+ new VpnInstanceOpDataEntryBuilder(vpnInstanceOpData).setRouteEntryId(routeIds).build(), DEFAULT_CALLBACK);
+ } else {
+ LOG.warn("No VPN Instance found for RD: {}", rd);
+ }
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<VrfEntry> identifier,
+ VrfEntry original, VrfEntry update) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<VrfEntry> identifier,
+ VrfEntry add) {
+ LOG.trace("Add Vrf Entry event - Key : {}, value : {}", identifier, add);
+ final VrfTablesKey key = identifier.firstKeyOf(VrfTables.class, VrfTablesKey.class);
+ String rd = key.getRouteDistinguisher();
+ Long label = add.getLabel();
+ VpnInstanceOpDataEntry vpn = getVpnInstanceOpData(rd);
+ if(vpn != null) {
+ List<Long> routeIds = vpn.getRouteEntryId();
+ if(routeIds == null) {
+ routeIds = new ArrayList<>();
+ }
+ LOG.debug("Adding label to vpn info - {}", label);
+ routeIds.add(label);
+ asyncWrite(LogicalDatastoreType.OPERATIONAL, VpnUtil.getVpnInstanceOpDataIdentifier(rd),
+ new VpnInstanceOpDataEntryBuilder(vpn).setRouteEntryId(routeIds).build(), DEFAULT_CALLBACK);
+ } else {
+ LOG.warn("No VPN Instance found for RD: {}", rd);
+ }
+ }
+ }
+
+ class VpnInstanceOpListener extends org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener<VpnInstanceOpDataEntry> {
+
+ public VpnInstanceOpListener() {
+ super(VpnInstanceOpDataEntry.class);
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<VpnInstanceOpDataEntry> identifier, VpnInstanceOpDataEntry del) {
+
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<VpnInstanceOpDataEntry> identifier, VpnInstanceOpDataEntry original, VpnInstanceOpDataEntry update) {
+ final VpnInstanceOpDataEntryKey key = identifier.firstKeyOf(VpnInstanceOpDataEntry.class, VpnInstanceOpDataEntryKey.class);
+ String vpnName = key.getVrfId();
+
+ LOG.trace("VpnInstanceOpListener update: vpn name {} interface count in Old VpnOp Instance {} in New VpnOp Instance {}" ,
+ vpnName, original.getVpnInterfaceCount(), update.getVpnInterfaceCount() );
+
+ //if((original.getVpnToDpnList().size() != update.getVpnToDpnList().size()) && (update.getVpnToDpnList().size() == 0)) {
+ if((original.getVpnInterfaceCount() != update.getVpnInterfaceCount()) && (update.getVpnInterfaceCount() == 0)) {
+ notifyTaskIfRequired(vpnName);
+ }
+ }
+
+ private void notifyTaskIfRequired(String vpnName) {
+ Runnable notifyTask = vpnOpMap.remove(vpnName);
+ if (notifyTask == null) {
+ LOG.trace("VpnInstanceOpListener update: No Notify Task queued for vpnName {}", vpnName);
+ return;
+ }
+ executorService.execute(notifyTask);
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<VpnInstanceOpDataEntry> identifier, VpnInstanceOpDataEntry add) {
+ }
+ }
+}
--- /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;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class VpnNotifyTask implements Runnable{
+ private static final Logger logger = LoggerFactory.getLogger(VpnNotifyTask.class);
+
+ @Override
+ public void run() {
+ logger.debug("Notify Task is running for the task {}", this);
+ synchronized (this) {
+ notifyAll();
+ }
+ }
+
+}
--- /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;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.bgpmanager.api.IBgpManager;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.utilities.InterfaceUtils;
+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.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.port.op.data.PortOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.port.op.data.PortOpDataEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.rd.to.elan.op.RdToElanOpEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.rd.to.elan.op.RdToElanOpEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.rd.to.elan.op.RdToElanOpEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.Subnetmap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.subnet.to.dpn.VpnInterfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.math.BigInteger;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+
+
+public class VpnSubnetRouteHandler implements NeutronvpnListener {
+ private static final Logger logger = LoggerFactory.getLogger(VpnSubnetRouteHandler.class);
+
+ private final DataBroker broker;
+ private SubnetOpDpnManager subOpDpnManager;
+ private final IBgpManager bgpManager;
+ private IdManagerService idManager;
+ private VpnInterfaceManager vpnInterfaceManager;
+
+ public VpnSubnetRouteHandler(final DataBroker db, IBgpManager bgpManager, VpnInterfaceManager vpnIntfManager) {
+ broker = db;
+ subOpDpnManager = new SubnetOpDpnManager(broker);
+ this.bgpManager = bgpManager;
+ this.vpnInterfaceManager = vpnIntfManager;
+ }
+
+ public void setIdManager(IdManagerService idManager) {
+ this.idManager = idManager;
+ }
+
+ @Override
+ public void onSubnetAddedToVpn(SubnetAddedToVpn notification) {
+ if (!notification.isExternalVpn()) {
+ return;
+ }
+
+ Uuid subnetId = notification.getSubnetId();
+ String vpnName = notification.getVpnName();
+ String subnetIp = notification.getSubnetIp();
+ Long elanTag = notification.getElanTag();
+
+ Preconditions.checkNotNull(subnetId, "SubnetId cannot be null or empty!");
+ Preconditions.checkNotNull(subnetIp, "SubnetPrefix cannot be null or empty!");
+ Preconditions.checkNotNull(vpnName, "VpnName cannot be null or empty!");
+ Preconditions.checkNotNull(elanTag, "ElanTag cannot be null or empty!");
+
+ logger.info("onSubnetAddedToVpn: Subnet" + subnetId.getValue() + " being added to vpn");
+ //TODO(vivek): Change this to use more granularized lock at subnetId level
+ synchronized (this) {
+ try {
+ //Create and add SubnetOpDataEntry object for this subnet to the SubnetOpData container
+ InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
+ child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
+ Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(broker,
+ LogicalDatastoreType.OPERATIONAL,
+ subOpIdentifier);
+ if (optionalSubs.isPresent()) {
+ logger.error("onSubnetAddedToVpn: SubnetOpDataEntry for subnet " + subnetId.getValue() +
+ " already detected to be present");
+ return;
+ }
+ logger.debug("onSubnetAddedToVpn: Creating new SubnetOpDataEntry node for subnet: " + subnetId.getValue());
+ Map<BigInteger, SubnetToDpn> subDpnMap = new HashMap<BigInteger, SubnetToDpn>();
+ SubnetOpDataEntry subOpEntry = null;
+ BigInteger dpnId = null;
+ BigInteger nhDpnId = null;
+ SubnetToDpn subDpn = null;
+
+ SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder().setKey(new SubnetOpDataEntryKey(subnetId));
+ subOpBuilder.setSubnetId(subnetId);
+ subOpBuilder.setSubnetCidr(subnetIp);
+ String rd = VpnUtil.getVpnRdFromVpnInstanceConfig(broker, vpnName);
+ if (rd == null) {
+ logger.error("onSubnetAddedToVpn: The VPN Instance name " + notification.getVpnName() + " does not have RD ");
+ return;
+ }
+ subOpBuilder.setVrfId(rd);
+ subOpBuilder.setVpnName(vpnName);
+ subOpBuilder.setSubnetToDpn(new ArrayList<SubnetToDpn>());
+ subOpBuilder.setRouteAdvState(TaskState.Na);
+ subOpBuilder.setElanTag(elanTag);
+
+ // First recover set of ports available in this subnet
+ InstanceIdentifier<Subnetmap> subMapid = InstanceIdentifier.builder(Subnetmaps.class).
+ child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
+ Optional<Subnetmap> sm = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, subMapid);
+ if (!sm.isPresent()) {
+ logger.error("onSubnetAddedToVpn: Unable to retrieve subnetmap entry for subnet : " + subnetId);
+ return;
+ }
+ Subnetmap subMap = sm.get();
+ List<Uuid> portList = subMap.getPortList();
+ if (portList != null) {
+ for (Uuid port: portList) {
+ Interface intfState = InterfaceUtils.getInterfaceStateFromOperDS(broker,port.getValue());
+ if (intfState != null) {
+ dpnId = InterfaceUtils.getDpIdFromInterface(intfState);
+ if (dpnId == null) {
+ logger.info("onSubnetAddedToVpn: Port " + port.getValue() + " is not assigned DPN yet, ignoring ");
+ continue;
+ }
+ subOpDpnManager.addPortOpDataEntry(port.getValue(), subnetId, dpnId);
+ if (intfState.getOperStatus() != OperStatus.Up) {
+ logger.info("onSubnetAddedToVpn: Port " + port.getValue() + " is not UP yet, ignoring ");
+ continue;
+ }
+ subDpn = subOpDpnManager.addInterfaceToDpn(subnetId, dpnId, port.getValue());
+ if (intfState.getOperStatus() == OperStatus.Up) {
+ // port is UP
+ subDpnMap.put(dpnId, subDpn);
+ if (nhDpnId == null) {
+ nhDpnId = dpnId;
+ }
+ }
+ } else {
+ subOpDpnManager.addPortOpDataEntry(port.getValue(), subnetId, null);
+ }
+ }
+ if (subDpnMap.size() > 0) {
+ subOpBuilder.setSubnetToDpn(new ArrayList<SubnetToDpn>(subDpnMap.values()));
+ }
+ }
+
+ if (nhDpnId != null) {
+ subOpBuilder.setNhDpnId(nhDpnId);
+ try {
+ /*
+ Write the subnet route entry to the FIB.
+ And also advertise the subnet route entry via BGP.
+ */
+ addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag);
+ advertiseSubnetRouteToBgp(rd, subnetIp, nhDpnId, vpnName, elanTag);
+ subOpBuilder.setRouteAdvState(TaskState.Done);
+ } catch (Exception ex) {
+ logger.error("onSubnetAddedToVpn: FIB rules and Advertising nhDpnId " + nhDpnId +
+ " information for subnet " + subnetId.getValue() + " to BGP failed {}", ex);
+ subOpBuilder.setRouteAdvState(TaskState.Pending);
+ }
+ } else {
+ try {
+ /*
+ Write the subnet route entry to the FIB.
+ NOTE: Will not advertise to BGP as NextHopDPN is not available yet.
+ */
+ addSubnetRouteToFib(rd, subnetIp, null, vpnName, elanTag);
+ } catch (Exception ex) {
+ logger.error("onSubnetAddedToVpn: FIB rules writing for subnet {} with exception {} " +
+ subnetId.getValue(), ex);
+ subOpBuilder.setRouteAdvState(TaskState.Pending);
+ }
+ }
+
+ subOpEntry = subOpBuilder.build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
+ logger.info("onSubnetAddedToVpn: Added subnetopdataentry to OP Datastore for subnet " + subnetId.getValue());
+ } catch (Exception ex) {
+ logger.error("Creation of SubnetOpDataEntry for subnet " +
+ subnetId.getValue() + " failed {}", ex);
+ } finally {
+ }
+ }
+ }
+
+ @Override
+ public void onSubnetDeletedFromVpn(SubnetDeletedFromVpn notification) {
+ Uuid subnetId = notification.getSubnetId();
+
+ if (!notification.isExternalVpn()) {
+ return;
+ }
+ logger.info("onSubnetDeletedFromVpn: Subnet" + subnetId.getValue() + " being removed to vpn");
+ //TODO(vivek): Change this to use more granularized lock at subnetId level
+ synchronized (this) {
+ try {
+ InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
+ child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
+ logger.trace(" Removing the SubnetOpDataEntry node for subnet: " + subnetId.getValue());
+ Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(broker,
+ LogicalDatastoreType.OPERATIONAL,
+ subOpIdentifier);
+ if (!optionalSubs.isPresent()) {
+ logger.error("onSubnetDeletedFromVpn: SubnetOpDataEntry for subnet " + subnetId.getValue() +
+ " not available in datastore");
+ return;
+ }
+ SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
+ List<SubnetToDpn> subDpnList = subOpBuilder.getSubnetToDpn();
+ for (SubnetToDpn subDpn: subDpnList) {
+ List<VpnInterfaces> vpnIntfList = subDpn.getVpnInterfaces();
+ for (VpnInterfaces vpnIntf: vpnIntfList) {
+ subOpDpnManager.removePortOpDataEntry(vpnIntf.getInterfaceName());
+ }
+ }
+ //Removing Stale Ports in portOpData
+ InstanceIdentifier<Subnetmap> subMapid = InstanceIdentifier.builder(Subnetmaps.class).
+ child(Subnetmap.class, new SubnetmapKey(subnetId)).build();
+ Optional<Subnetmap> sm = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, subMapid);
+ if (!sm.isPresent()) {
+ logger.error("Stale ports removal: Unable to retrieve subnetmap entry for subnet : " + subnetId);
+ }
+ Subnetmap subMap = sm.get();
+ List<Uuid> portList = subMap.getPortList();
+ if(portList!=null){
+ InstanceIdentifier<PortOpData> portOpIdentifier = InstanceIdentifier.builder(PortOpData.class).build();
+ Optional<PortOpData> optionalPortOp = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
+ if(!optionalPortOp.isPresent()){
+ logger.error("Stale ports removal: Cannot delete port. Not available in data store");
+ return;
+ } else{
+ PortOpData portOpData = optionalPortOp.get();
+ List<PortOpDataEntry> portOpDataList = portOpData.getPortOpDataEntry();
+ if(portOpDataList!=null){
+ for(PortOpDataEntry portOpDataListEntry : portOpDataList){
+ if(portList.contains(new Uuid(portOpDataListEntry.getPortId()))){
+ logger.trace("Removing stale port: " + portOpDataListEntry + "for dissociated subnetId: " + subnetId);
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, portOpIdentifier.
+ child(PortOpDataEntry.class, new PortOpDataEntryKey(portOpDataListEntry.getKey())));
+ }
+ }
+ }
+ }
+ }
+
+ String rd = subOpBuilder.getVrfId();
+ String subnetIp = subOpBuilder.getSubnetCidr();
+ BigInteger nhDpnId = subOpBuilder.getNhDpnId();
+ MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier);
+ logger.trace("Removed subnetopdataentry successfully to CONFIG Datastore");
+ try {
+ //Withdraw the routes for all the interfaces on this subnet
+ //Remove subnet route entry from FIB
+ withdrawSubnetRoutefromBgp(rd, subnetIp);
+ deleteSubnetRouteFromFib(rd, subnetIp);
+ } catch (Exception ex) {
+ logger.error("onSubnetAddedToVpn: Withdrawing routes from BGP for subnet " +
+ subnetId.getValue() + " failed {}" + ex);
+ }
+ } catch (Exception ex) {
+ logger.error("Removal of SubnetOpDataEntry for subnet " +
+ subnetId.getValue() + " failed {}" + ex);
+ } finally {
+ }
+ }
+ }
+
+ @Override
+ public void onSubnetUpdatedInVpn(SubnetUpdatedInVpn notification) {
+ Uuid subnetId = notification.getSubnetId();
+ String vpnName = notification.getVpnName();
+ String subnetIp = notification.getSubnetIp();
+ Long elanTag = notification.getElanTag();
+
+ Preconditions.checkNotNull(subnetId, "SubnetId cannot be null or empty!");
+ Preconditions.checkNotNull(subnetIp, "SubnetPrefix cannot be null or empty!");
+ Preconditions.checkNotNull(vpnName, "VpnName cannot be null or empty!");
+ Preconditions.checkNotNull(elanTag, "ElanTag cannot be null or empty!");
+
+ InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
+ child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
+ Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(broker,
+ LogicalDatastoreType.OPERATIONAL,
+ subOpIdentifier);
+ if (optionalSubs.isPresent()) {
+ if (!notification.isExternalVpn()) {
+ SubnetDeletedFromVpnBuilder bldr = new SubnetDeletedFromVpnBuilder().setVpnName(vpnName);
+ bldr.setElanTag(elanTag).setExternalVpn(true).setSubnetIp(subnetIp).setSubnetId(subnetId);
+ onSubnetDeletedFromVpn(bldr.build());
+ }
+ // TODO(vivek): Something got updated, but we donot know what ?
+ } else {
+ if (notification.isExternalVpn()) {
+ SubnetAddedToVpnBuilder bldr = new SubnetAddedToVpnBuilder().setVpnName(vpnName).setElanTag(elanTag);
+ bldr.setSubnetIp(subnetIp).setSubnetId(subnetId).setExternalVpn(true);;
+ onSubnetAddedToVpn(bldr.build());
+ }
+ // TODO(vivek): Something got updated, but we donot know what ?
+ }
+ }
+
+ @Override
+ public void onPortAddedToSubnet(PortAddedToSubnet notification) {
+ Uuid subnetId = notification.getSubnetId();
+ Uuid portId = notification.getPortId();
+
+ logger.info("onPortAddedToSubnet: Port " + portId.getValue() + " being added to subnet " + subnetId.getValue());
+ //TODO(vivek): Change this to use more granularized lock at subnetId level
+ synchronized (this) {
+ try {
+ InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
+ child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
+
+ Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
+ subOpIdentifier);
+ if (!optionalSubs.isPresent()) {
+ logger.info("onPortAddedToSubnet: Port " + portId.getValue() + " is part of a subnet " + subnetId.getValue() +
+ " that is not in VPN, ignoring");
+ return;
+ }
+ Interface intfState = InterfaceUtils.getInterfaceStateFromOperDS(broker,portId.getValue());
+ if (intfState == null) {
+ // Interface State not yet available
+ subOpDpnManager.addPortOpDataEntry(portId.getValue(), subnetId, null);
+ return;
+ }
+ BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(intfState);
+ if (dpnId == null) {
+ logger.info("onPortAddedToSubnet: Port " + portId.getValue() + " is not assigned DPN yet, ignoring ");
+ return;
+ }
+ subOpDpnManager.addPortOpDataEntry(portId.getValue(), subnetId, dpnId);
+ if (intfState.getOperStatus() != OperStatus.Up) {
+ logger.info("onPortAddedToSubnet: Port " + portId.getValue() + " is not UP yet, ignoring ");
+ return;
+ }
+ logger.debug("onPortAddedToSubnet: Updating the SubnetOpDataEntry node for subnet: " + subnetId.getValue());
+ SubnetToDpn subDpn = subOpDpnManager.addInterfaceToDpn(subnetId, dpnId, portId.getValue());
+ if (subDpn == null) {
+ return;
+ }
+ SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
+ List<SubnetToDpn> subDpnList = subOpBuilder.getSubnetToDpn();
+ subDpnList.add(subDpn);
+ subOpBuilder.setSubnetToDpn(subDpnList);
+ if (subOpBuilder.getNhDpnId() == null) {
+ subOpBuilder.setNhDpnId(dpnId);
+ }
+ BigInteger nhDpnId = subOpBuilder.getNhDpnId();
+ String rd = subOpBuilder.getVrfId();
+ String subnetIp = subOpBuilder.getSubnetCidr();
+ String vpnName = subOpBuilder.getVpnName();
+ Long elanTag = subOpBuilder.getElanTag();
+ if ((subOpBuilder.getRouteAdvState() == TaskState.Pending) ||
+ (subOpBuilder.getRouteAdvState() == TaskState.Na)) {
+ try {
+ // Write the Subnet Route Entry to FIB
+ // Advertise BGP Route here and set route_adv_state to DONE
+ addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag);
+ advertiseSubnetRouteToBgp(rd, subnetIp, nhDpnId, vpnName, elanTag);
+ subOpBuilder.setRouteAdvState(TaskState.Done);
+ } catch (Exception ex) {
+ logger.error("onPortAddedToSubnet: Advertising NextHopDPN "+ nhDpnId +
+ " information for subnet " + subnetId.getValue() + " to BGP failed {}", ex);
+ }
+ }
+ SubnetOpDataEntry subOpEntry = subOpBuilder.build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
+ logger.info("onPortAddedToSubnet: Updated subnetopdataentry to OP Datastore for port " + portId.getValue());
+
+ } catch (Exception ex) {
+ logger.error("Creation of SubnetOpDataEntry for subnet " +
+ subnetId.getValue() + " failed {}", ex);
+ } finally {
+ }
+ }
+ }
+
+ @Override
+ public void onPortRemovedFromSubnet(PortRemovedFromSubnet notification) {
+ Uuid subnetId = notification.getSubnetId();
+ Uuid portId = notification.getPortId();
+
+ logger.info("onPortRemovedFromSubnet: Port " + portId.getValue() + " being removed from subnet " + subnetId.getValue());
+ //TODO(vivek): Change this to use more granularized lock at subnetId level
+ synchronized (this) {
+ try {
+ PortOpDataEntry portOpEntry = subOpDpnManager.removePortOpDataEntry(portId.getValue());
+ if (portOpEntry == null) {
+ return;
+ }
+ BigInteger dpnId = portOpEntry.getDpnId();
+ if (dpnId == null) {
+ logger.debug("onPortRemovedFromSubnet: Port {} does not have a DPNId associated, ignoring", portId.getValue());
+ return;
+ }
+ logger.debug("onPortRemovedFromSubnet: Updating the SubnetOpDataEntry node for subnet: " + subnetId.getValue());
+ boolean last = subOpDpnManager.removeInterfaceFromDpn(subnetId, dpnId, portId.getValue());
+ InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
+ child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
+ Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
+ subOpIdentifier);
+ if (!optionalSubs.isPresent()) {
+ logger.info("onPortRemovedFromSubnet: Port " + portId.getValue() + " is part of a subnet " + subnetId.getValue() +
+ " that is not in VPN, ignoring");
+ return;
+ }
+ SubnetOpDataEntry subOpEntry = null;
+ List<SubnetToDpn> subDpnList = null;
+ SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
+ String rd = subOpBuilder.getVrfId();
+ String subnetIp = subOpBuilder.getSubnetCidr();
+ String vpnName = subOpBuilder.getVpnName();
+ Long elanTag = subOpBuilder.getElanTag();
+ BigInteger nhDpnId = subOpBuilder.getNhDpnId();
+ if ((nhDpnId != null) && (nhDpnId.equals(dpnId))) {
+ // select another NhDpnId
+ if (last) {
+ logger.debug("onPortRemovedFromSubnet: Last port " + portId + " on the subnet: " + subnetId.getValue());
+ // last port on this DPN, so we need to swap the NHDpnId
+ subDpnList = subOpBuilder.getSubnetToDpn();
+ if (subDpnList.isEmpty()) {
+ subOpBuilder.setNhDpnId(null);
+ try {
+ // withdraw route from BGP
+ deleteSubnetRouteFromFib(rd, subnetIp);
+ withdrawSubnetRoutefromBgp(rd, subnetIp);
+ subOpBuilder.setRouteAdvState(TaskState.Na);
+ } catch (Exception ex) {
+ logger.error("onPortRemovedFromSubnet: Withdrawing NextHopDPN " + dpnId + " information for subnet " +
+ subnetId.getValue() + " from BGP failed ", ex);
+ subOpBuilder.setRouteAdvState(TaskState.Pending);
+ }
+ } else {
+ nhDpnId = subDpnList.get(0).getDpnId();
+ subOpBuilder.setNhDpnId(nhDpnId);
+ logger.debug("onInterfaceDown: Swapping the Designated DPN to " + nhDpnId + " for subnet " + subnetId.getValue());
+ try {
+ // Best effort Withdrawal of route from BGP for this subnet
+ // Advertise the new NexthopIP to BGP for this subnet
+ withdrawSubnetRoutefromBgp(rd, subnetIp);
+ addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag);
+ advertiseSubnetRouteToBgp(rd, subnetIp, nhDpnId, vpnName, elanTag);
+ subOpBuilder.setRouteAdvState(TaskState.Done);
+ } catch (Exception ex) {
+ logger.error("onPortRemovedFromSubnet: Swapping Withdrawing NextHopDPN " + dpnId +
+ " information for subnet " + subnetId.getValue() +
+ " to BGP failed {}" + ex);
+ subOpBuilder.setRouteAdvState(TaskState.Pending);
+ }
+ }
+ }
+ }
+ subOpEntry = subOpBuilder.build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
+ logger.info("onPortRemovedFromSubnet: Updated subnetopdataentry to OP Datastore removing port " + portId.getValue());
+ } catch (Exception ex) {
+ logger.error("Creation of SubnetOpDataEntry for subnet " +
+ subnetId.getValue() + " failed {}" + ex);
+ } finally {
+ }
+ }
+ }
+
+ public void onInterfaceUp(Interface intfState) {
+
+ logger.info("onInterfaceUp: Port " + intfState.getName());
+ //TODO(vivek): Change this to use more granularized lock at subnetId level
+ synchronized (this) {
+ SubnetToDpn subDpn = null;
+ String intfName = intfState.getName();
+ PortOpDataEntry portOpEntry = subOpDpnManager.getPortOpDataEntry(intfName);
+ if (portOpEntry == null) {
+ logger.info("onInterfaceUp: Port " + intfState.getName() + "is part of a subnet not in VPN, ignoring");
+ return;
+ }
+ BigInteger dpnId = portOpEntry.getDpnId();
+ if (dpnId == null) {
+ dpnId = InterfaceUtils.getDpIdFromInterface(intfState);
+ if (dpnId == null) {
+ logger.error("onInterfaceUp: Unable to determine the DPNID for port " + intfName);
+ return;
+ }
+ }
+ Uuid subnetId = portOpEntry.getSubnetId();
+ try {
+ InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
+ child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
+ Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
+ subOpIdentifier);
+ if (!optionalSubs.isPresent()) {
+ logger.error("onInterfaceUp: SubnetOpDataEntry for subnet " + subnetId.getValue() +
+ " is not available");
+ return;
+ }
+
+ SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
+ logger.debug("onInterfaceUp: Updating the SubnetOpDataEntry node for subnet: " + subnetId.getValue());
+ subOpDpnManager.addPortOpDataEntry(intfName, subnetId, dpnId);
+ subDpn = subOpDpnManager.addInterfaceToDpn(subnetId, dpnId, intfName);
+ if (subDpn == null) {
+ return;
+ }
+ List<SubnetToDpn> subDpnList = subOpBuilder.getSubnetToDpn();
+ subDpnList.add(subDpn);
+ subOpBuilder.setSubnetToDpn(subDpnList);
+ if (subOpBuilder.getNhDpnId() == null) {
+ subOpBuilder.setNhDpnId(dpnId);
+ }
+ BigInteger nhDpnId = subOpBuilder.getNhDpnId();
+ String rd = subOpBuilder.getVrfId();
+ String subnetIp = subOpBuilder.getSubnetCidr();
+ String vpnName = subOpBuilder.getVpnName();
+ Long elanTag = subOpBuilder.getElanTag();
+ if ((subOpBuilder.getRouteAdvState() == TaskState.Pending) || (subOpBuilder.getRouteAdvState() == TaskState.Na)) {
+ try {
+ // Write the Subnet Route Entry to FIB
+ // Advertise BGP Route here and set route_adv_state to DONE
+ addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag);
+ advertiseSubnetRouteToBgp(rd, subnetIp, nhDpnId, vpnName, elanTag);
+ subOpBuilder.setRouteAdvState(TaskState.Done);
+ } catch (Exception ex) {
+ logger.error("onInterfaceUp: Advertising NextHopDPN " + nhDpnId + " information for subnet " +
+ subnetId.getValue() + " to BGP failed {}" + ex);
+ }
+ }
+ SubnetOpDataEntry subOpEntry = subOpBuilder.build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
+ logger.info("onInterfaceUp: Updated subnetopdataentry to OP Datastore port up " + intfName);
+ } catch (Exception ex) {
+ logger.error("Creation of SubnetOpDataEntry for subnet " +
+ subnetId.getValue() + " failed {}" + ex);
+ } finally {
+ }
+ }
+ }
+
+ public void onInterfaceDown(Interface intfState) {
+ logger.info("onInterfaceDown: Port " + intfState.getName());
+ //TODO(vivek): Change this to use more granularized lock at subnetId level
+ synchronized (this) {
+ String intfName = intfState.getName();
+ PortOpDataEntry portOpEntry = subOpDpnManager.getPortOpDataEntry(intfName);
+ if (portOpEntry == null) {
+ logger.info("onInterfaceDown: Port " + intfState.getName() + "is part of a subnet not in VPN, ignoring");
+ return;
+ }
+ BigInteger dpnId = portOpEntry.getDpnId();
+ if (dpnId == null) {
+ dpnId = InterfaceUtils.getDpIdFromInterface(intfState);
+ if (dpnId == null) {
+ logger.error("onInterfaceDown: Unable to determine the DPNID for port " + intfName);
+ return;
+ }
+ }
+ Uuid subnetId = portOpEntry.getSubnetId();
+ try {
+ logger.debug("onInterfaceDown: Updating the SubnetOpDataEntry node for subnet: " + subnetId.getValue());
+ boolean last = subOpDpnManager.removeInterfaceFromDpn(subnetId, dpnId, intfName);
+ InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
+ child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
+ Optional<SubnetOpDataEntry> optionalSubs = VpnUtil.read(broker,
+ LogicalDatastoreType.OPERATIONAL,
+ subOpIdentifier);
+ if (!optionalSubs.isPresent()) {
+ logger.error("onInterfaceDown: SubnetOpDataEntry for subnet " + subnetId.getValue() +
+ " is not available");
+ return;
+ }
+ SubnetOpDataEntry subOpEntry = null;
+ List<SubnetToDpn> subDpnList = null;
+ SubnetOpDataEntryBuilder subOpBuilder = new SubnetOpDataEntryBuilder(optionalSubs.get());
+ String rd = subOpBuilder.getVrfId();
+ String subnetIp = subOpBuilder.getSubnetCidr();
+ String vpnName = subOpBuilder.getVpnName();
+ Long elanTag = subOpBuilder.getElanTag();
+ BigInteger nhDpnId = subOpBuilder.getNhDpnId();
+ if ((nhDpnId != null) && (nhDpnId.equals(dpnId))) {
+ // select another NhDpnId
+ if (last) {
+ logger.debug("onInterfaceDown: Last active port " + intfState.getName() + " on the subnet: " + subnetId.getValue());
+ // last port on this DPN, so we need to swap the NHDpnId
+ subDpnList = subOpBuilder.getSubnetToDpn();
+ if (subDpnList.isEmpty()) {
+ subOpBuilder.setNhDpnId(null);
+ try {
+ // Withdraw route from BGP for this subnet
+ deleteSubnetRouteFromFib(rd, subnetIp);
+ withdrawSubnetRoutefromBgp(rd, subnetIp);
+ subOpBuilder.setRouteAdvState(TaskState.Na);
+ } catch (Exception ex) {
+ logger.error("onInterfaceDown: Withdrawing NextHopDPN " + dpnId + " information for subnet " +
+ subnetId.getValue() + " from BGP failed {}" + ex);
+ subOpBuilder.setRouteAdvState(TaskState.Pending);
+ }
+ } else {
+ nhDpnId = subDpnList.get(0).getDpnId();
+ subOpBuilder.setNhDpnId(nhDpnId);
+ logger.debug("onInterfaceDown: Swapping the Designated DPN to " + nhDpnId + " for subnet " + subnetId.getValue());
+ try {
+ // Best effort Withdrawal of route from BGP for this subnet
+ withdrawSubnetRoutefromBgp(rd, subnetIp);
+ addSubnetRouteToFib(rd, subnetIp, nhDpnId, vpnName, elanTag);
+ advertiseSubnetRouteToBgp(rd, subnetIp, nhDpnId, vpnName, elanTag);
+ subOpBuilder.setRouteAdvState(TaskState.Done);
+ } catch (Exception ex) {
+ logger.error("onInterfaceDown: Swapping Withdrawing NextHopDPN " + dpnId + " information for subnet " +
+ subnetId.getValue() + " to BGP failed {}" + ex);
+ subOpBuilder.setRouteAdvState(TaskState.Pending);
+ }
+ }
+ }
+ }
+ subOpEntry = subOpBuilder.build();
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subOpEntry);
+ logger.info("onInterfaceDown: Updated subnetopdataentry to OP Datastore port down " + intfName);
+ } catch (Exception ex) {
+ logger.error("Creation of SubnetOpDataEntry for subnet " +
+ subnetId.getValue() + " failed {}" + ex);
+ } finally {
+ }
+ }
+ }
+
+ private static void setRdToElanOpEntry(DataBroker broker,
+ String rd, String subnetIp, String nextHopIp, String vpnName,
+ Long elanTag) {
+ RdToElanOpEntryBuilder rdElanBuilder = null;
+ RdToElanOpEntry rdElan = null;
+
+ try {
+ InstanceIdentifier<RdToElanOpEntry> rdIdentifier = InstanceIdentifier.builder(RdToElanOp.class).
+ child(RdToElanOpEntry.class, new RdToElanOpEntryKey(rd, subnetIp)).build();
+ Optional<RdToElanOpEntry> optionalRd = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, rdIdentifier);
+ if (!optionalRd.isPresent()) {
+ // Create PortOpDataEntry only if not present
+ rdElanBuilder = new RdToElanOpEntryBuilder().setKey(new RdToElanOpEntryKey(rd,subnetIp));
+ rdElanBuilder.setRd(rd).setSubnetIp(subnetIp).setNextHopIp(nextHopIp);
+ rdElanBuilder.setElanTag(elanTag);
+ rdElanBuilder.setVpnName(vpnName);
+ rdElan = rdElanBuilder.build();
+ } else {
+ rdElanBuilder = new RdToElanOpEntryBuilder(optionalRd.get());
+ rdElanBuilder.setRd(rd).setSubnetIp(subnetIp).setNextHopIp(nextHopIp);
+ rdElanBuilder.setElanTag(elanTag);
+ rdElanBuilder.setVpnName(vpnName);
+ rdElan = rdElanBuilder.build();
+ }
+ MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, rdIdentifier, rdElan);
+ logger.info("Creating RdToElan entry Rd {} SubnetIp {} NextHopIp {} Elan {} " ,rd, subnetIp, nextHopIp, elanTag);
+ } catch (Exception ex) {
+ logger.error("Exception when creating RdToElan entry {}" + ex);
+ } finally {
+ }
+ }
+
+ private void addSubnetRouteToFib(String rd, String subnetIp, BigInteger nhDpnId, String vpnName,
+ Long elanTag) {
+ Preconditions.checkNotNull(rd, "RouteDistinguisher cannot be null or empty!");
+ Preconditions.checkNotNull(subnetIp, "SubnetRouteIp cannot be null or empty!");
+ Preconditions.checkNotNull(vpnName, "vpnName cannot be null or empty!");
+ Preconditions.checkNotNull(elanTag, "elanTag cannot be null or empty!");
+ String nexthopIp = null;
+ if (nhDpnId != null) {
+ nexthopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, nhDpnId);
+ }
+ int label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
+ VpnUtil.getNextHopLabelKey(rd, subnetIp));
+ setRdToElanOpEntry(broker, rd, subnetIp, nexthopIp, vpnName, elanTag);
+ vpnInterfaceManager.addFibEntryToDS(rd, subnetIp, nexthopIp, label);
+ }
+
+ private void deleteSubnetRouteFromFib(String rd, String subnetIp) {
+ Preconditions.checkNotNull(rd, "RouteDistinguisher cannot be null or empty!");
+ Preconditions.checkNotNull(subnetIp, "SubnetRouteIp cannot be null or empty!");
+ vpnInterfaceManager.removeFibEntryFromDS(rd, subnetIp);
+ }
+
+ private void advertiseSubnetRouteToBgp(String rd, String subnetIp, BigInteger nhDpnId, String vpnName,
+ Long elanTag) throws Exception {
+ Preconditions.checkNotNull(rd, "RouteDistinguisher cannot be null or empty!");
+ Preconditions.checkNotNull(subnetIp, "SubnetRouteIp cannot be null or empty!");
+ Preconditions.checkNotNull(elanTag, "elanTag cannot be null or empty!");
+ Preconditions.checkNotNull(nhDpnId, "nhDpnId cannot be null or empty!");
+ Preconditions.checkNotNull(vpnName, "vpnName cannot be null or empty!");
+ String nexthopIp = null;
+ nexthopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, nhDpnId);
+ if (nexthopIp == null) {
+ logger.error("createSubnetRouteInVpn: Unable to obtain endpointIp address for DPNId " + nhDpnId);
+ throw new Exception("Unable to obtain endpointIp address for DPNId " + nhDpnId);
+ }
+ int label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
+ VpnUtil.getNextHopLabelKey(rd, subnetIp));
+ setRdToElanOpEntry(broker, rd, subnetIp, nexthopIp, vpnName, elanTag);
+ try {
+ bgpManager.advertisePrefix(rd, subnetIp, nexthopIp, label);
+ } catch (Exception e) {
+ logger.error("Subnet route not advertised for rd " + rd + " failed ", e);
+ throw e;
+ }
+ }
+
+ private void withdrawSubnetRoutefromBgp(String rd, String subnetIp) throws Exception {
+ Preconditions.checkNotNull(rd, "RouteDistinguisher cannot be null or empty!");
+ Preconditions.checkNotNull(subnetIp, "SubnetIp cannot be null or empty!");
+ try {
+ bgpManager.withdrawPrefix(rd, subnetIp);
+ } catch (Exception e) {
+ logger.error("Subnet route not advertised for rd " + rd + " failed ", e);
+ throw e;
+ }
+ }
+
+ @Override
+ public void onRouterAssociatedToVpn(RouterAssociatedToVpn notification) {
+ }
+
+ @Override
+ public void onRouterDisassociatedFromVpn(RouterDisassociatedFromVpn notification) {
+
+ }
+}
+
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.vpnservice;
+
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.List;
+
+import com.google.common.base.Optional;
+import com.google.common.primitives.Ints;
+import com.google.common.util.concurrent.CheckedFuture;
+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.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
+import org.opendaylight.vpnservice.mdsalutil.packet.ARP;
+import org.opendaylight.vpnservice.mdsalutil.packet.Ethernet;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
+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.VpnInstances;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
+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.l3vpn.rev130911.*;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacenciesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.VpnIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.VpnIdsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.router.interfaces.RouterInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.router.interfaces.RouterInterface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.router.interfaces.RouterInterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.Vpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.VpnKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.Extraroute;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanDpnInterfaces;
+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.fibmanager.rev150330.FibEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools;
+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.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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+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.vpnservice.l3nexthop.rev150409.L3nexthop;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.VpnNexthops;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.VpnNexthopsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.NeutronPortData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.neutron.port.data.PortFixedipToPortName;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.neutron.port.data.PortFixedipToPortNameKey;
+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.ElanTagNameMap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.tag.name.map.ElanTagNameKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class VpnUtil {
+ private static final Logger LOG = LoggerFactory.getLogger(VpnUtil.class);
+ private static final int DEFAULT_PREFIX_LENGTH = 32;
+ private static final String PREFIX_SEPARATOR = "/";
+
+ static InstanceIdentifier<VpnInterface> getVpnInterfaceIdentifier(String vpnInterfaceName) {
+ return InstanceIdentifier.builder(VpnInterfaces.class)
+ .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).build();
+ }
+
+ static InstanceIdentifier<VpnInstance> getVpnInstanceIdentifier(String vpnName) {
+ return InstanceIdentifier.builder(VpnInstances.class)
+ .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
+ }
+
+ static VpnInterface getVpnInterface(String intfName, String vpnName, Adjacencies aug) {
+ return new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(intfName)).setVpnInstanceName(vpnName)
+ .addAugmentation(Adjacencies.class, aug)
+ .build();
+ }
+
+ static InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(long vpnId, String ipPrefix) {
+ return InstanceIdentifier.builder(PrefixToInterface.class)
+ .child(VpnIds.class, new VpnIdsKey(vpnId)).child(Prefixes.class,
+ new PrefixesKey(ipPrefix)).build();
+ }
+
+ static Prefixes getPrefixToInterface(BigInteger dpId, String vpnInterfaceName, String ipPrefix) {
+ return new PrefixesBuilder().setDpnId(dpId).setVpnInterfaceName(
+ vpnInterfaceName).setIpAddress(ipPrefix).build();
+ }
+
+ static InstanceIdentifier<Extraroute> getVpnToExtrarouteIdentifier(String vrfId, String ipPrefix) {
+ return InstanceIdentifier.builder(VpnToExtraroute.class)
+ .child(Vpn.class, new VpnKey(vrfId)).child(Extraroute.class,
+ new ExtrarouteKey(ipPrefix)).build();
+ }
+
+ static Extraroute getVpnToExtraroute(String ipPrefix, String nextHop) {
+ return new ExtrarouteBuilder().setPrefix(ipPrefix).setNexthopIp(nextHop).build();
+ }
+
+ static Adjacencies
+ getVpnInterfaceAugmentation(List<Adjacency> nextHops) {
+ return new AdjacenciesBuilder().setAdjacency(nextHops).build();
+ }
+
+ public static InstanceIdentifier<IdPool> getPoolId(String poolName){
+ InstanceIdentifier.InstanceIdentifierBuilder<IdPool> idBuilder =
+ InstanceIdentifier.builder(IdPools.class).child(IdPool.class, new IdPoolKey(poolName));
+ InstanceIdentifier<IdPool> id = idBuilder.build();
+ return id;
+ }
+
+ static InstanceIdentifier<VpnInterfaces> getVpnInterfacesIdentifier() {
+ return InstanceIdentifier.builder(VpnInterfaces.class).build();
+ }
+
+ static InstanceIdentifier<Interface> getInterfaceIdentifier(String interfaceName) {
+ return InstanceIdentifier.builder(Interfaces.class)
+ .child(Interface.class, new InterfaceKey(interfaceName)).build();
+ }
+
+ static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
+ return InstanceIdentifier.builder(VpnInstanceOpData.class)
+ .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd))
+ .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId)).build();
+ }
+
+ public static BigInteger getCookieArpFlow(int interfaceTag) {
+ return VpnConstants.COOKIE_L3_BASE.add(new BigInteger("0110000", 16)).add(
+ BigInteger.valueOf(interfaceTag));
+ }
+
+ public static String getFlowRef(BigInteger dpnId, short tableId, int ethType, int lPortTag, int arpType) {
+ return new StringBuffer().append(VpnConstants.FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
+ .append(tableId).append(NwConstants.FLOWID_SEPARATOR).append(ethType).append(lPortTag)
+ .append(NwConstants.FLOWID_SEPARATOR).append(arpType).toString();
+ }
+
+ public static int 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 {
+ LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when getting Unique Id",e);
+ }
+ return 0;
+ }
+
+ public static void releaseId(IdManagerService idManager, String poolName, String idKey) {
+ ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
+ try {
+ Future<RpcResult<Void>> result = idManager.releaseId(idInput);
+ RpcResult<Void> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when getting Unique Id for key {}", idKey, e);
+ }
+ }
+
+ public static String getNextHopLabelKey(String rd, String prefix){
+ String key = rd + VpnConstants.SEPARATOR + prefix;
+ return key;
+ }
+
+ public static long getVpnId(DataBroker broker, String vpnName) {
+
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
+ = getVpnInstanceToVpnIdIdentifier(vpnName);
+ Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
+ = read(broker, LogicalDatastoreType.CONFIGURATION, id);
+
+ long vpnId = VpnConstants.INVALID_ID;
+ if(vpnInstance.isPresent()) {
+ vpnId = vpnInstance.get().getVpnId();
+ }
+ return vpnId;
+ }
+
+ public static String getVpnRd(DataBroker broker, String vpnName) {
+
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
+ = getVpnInstanceToVpnIdIdentifier(vpnName);
+ Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
+ = read(broker, LogicalDatastoreType.CONFIGURATION, id);
+
+ String rd = null;
+ if(vpnInstance.isPresent()) {
+ rd = vpnInstance.get().getVrfId();
+ }
+ return rd;
+ }
+
+ static String getVpnRdFromVpnInstanceConfig(DataBroker broker, String vpnName) {
+ InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
+ .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
+ Optional<VpnInstance> vpnInstance = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
+ String rd = null;
+ if(vpnInstance.isPresent()) {
+ VpnInstance instance = vpnInstance.get();
+ VpnAfConfig config = instance.getIpv4Family();
+ rd = config.getRouteDistinguisher();
+ }
+ return rd;
+ }
+
+ static org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
+ getVpnInstanceToVpnId(String vpnName, long vpnId, String rd) {
+ return new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceBuilder()
+ .setVpnId(vpnId).setVpnInstanceName(vpnName).setVrfId(rd).build();
+
+ }
+
+ static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
+ getVpnInstanceToVpnIdIdentifier(String vpnName) {
+ return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
+ .child(org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance.class,
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
+ }
+
+ static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String rd) {
+ return InstanceIdentifier.builder(VpnInstanceOpData.class)
+ .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
+ }
+
+ static VpnInstanceOpDataEntry getVpnInstanceOpDataBuilder(String rd, long vpnId) {
+ return new VpnInstanceOpDataEntryBuilder().setVrfId(rd).setVpnId(vpnId).build();
+ }
+
+ static VpnInstanceOpDataEntry updateIntfCntInVpnInstOpData(Long count, String vrfId) {
+ return new VpnInstanceOpDataEntryBuilder().setVpnInterfaceCount(count).setVrfId(vrfId).build();
+ }
+
+ static InstanceIdentifier<RouterInterface> getRouterInterfaceId(String interfaceName) {
+ return InstanceIdentifier.builder(RouterInterfaces.class)
+ .child(RouterInterface.class, new RouterInterfaceKey(interfaceName)).build();
+ }
+
+ static RouterInterface getRouterInterface(String interfaceName, String routerName) {
+ return new RouterInterfaceBuilder().setKey(new RouterInterfaceKey(interfaceName))
+ .setInterfaceName(interfaceName).setRouterName(routerName).build();
+ }
+
+ static VpnInstanceOpDataEntry getVpnInstanceOpData(DataBroker broker, String rd) {
+ InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
+ Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = read(broker, LogicalDatastoreType.OPERATIONAL, id);
+ if(vpnInstanceOpData.isPresent()) {
+ return vpnInstanceOpData.get();
+ }
+ return null;
+ }
+
+ static VpnInterface getConfiguredVpnInterface(DataBroker broker, String interfaceName) {
+ InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
+ Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
+
+ if (configuredVpnInterface.isPresent()) {
+ return configuredVpnInterface.get();
+ }
+ return null;
+ }
+
+ static VpnInterface getOperationalVpnInterface(DataBroker broker, String interfaceName) {
+ InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
+ Optional<VpnInterface> operationalVpnInterface = read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
+
+ if (operationalVpnInterface.isPresent()) {
+ return operationalVpnInterface.get();
+ }
+ return null;
+ }
+
+ static boolean isVpnInterfaceConfigured(DataBroker broker, String interfaceName)
+ {
+ InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
+ Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
+
+ if (configuredVpnInterface.isPresent()) {
+ return true;
+ }
+ return false;
+ }
+
+ static String getIpPrefix(String prefix) {
+ String prefixValues[] = prefix.split("/");
+ if (prefixValues.length == 1) {
+ prefix = prefix + PREFIX_SEPARATOR + DEFAULT_PREFIX_LENGTH ;
+ }
+ return prefix;
+ }
+
+ static final FutureCallback<Void> DEFAULT_CALLBACK =
+ new FutureCallback<Void>() {
+ public void onSuccess(Void result) {
+ LOG.debug("Success in Datastore operation");
+ }
+
+ public void onFailure(Throwable error) {
+ LOG.error("Error in Datastore operation", error);
+ };
+ };
+
+ 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);
+ } finally {
+ tx.close();
+ }
+
+ return result;
+ }
+
+ static <T extends DataObject> void asyncUpdate(DataBroker broker, LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.merge(datastoreType, path, data, true);
+ Futures.addCallback(tx.submit(), callback);
+ }
+
+ static <T extends DataObject> void asyncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.put(datastoreType, path, data, true);
+ Futures.addCallback(tx.submit(), callback);
+ }
+
+ 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) {
+ LOG.error("Error writing to datastore (path, data) : ({}, {})", path, data);
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+
+ public static <T extends DataObject> void syncUpdate(DataBroker broker, LogicalDatastoreType datastoreType,
+ InstanceIdentifier<T> path, T data) {
+ WriteTransaction tx = broker.newWriteOnlyTransaction();
+ tx.merge(datastoreType, path, data, true);
+ CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+ try {
+ futures.get();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Error writing to datastore (path, data) : ({}, {})", path, data);
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+
+ public static long getRemoteBCGroup(long elanTag) {
+ return VpnConstants.ELAN_GID_MIN + ((elanTag % VpnConstants.ELAN_GID_MIN) *2);
+ }
+
+ // interface-index-tag operational container
+ public static IfIndexInterface getInterfaceInfoByInterfaceTag(DataBroker broker, long interfaceTag) {
+ InstanceIdentifier<IfIndexInterface> interfaceId = getInterfaceInfoEntriesOperationalDataPath(interfaceTag);
+ Optional<IfIndexInterface> existingInterfaceInfo = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
+ if(existingInterfaceInfo.isPresent()) {
+ return existingInterfaceInfo.get();
+ }
+ return null;
+ }
+
+ private static InstanceIdentifier<IfIndexInterface> getInterfaceInfoEntriesOperationalDataPath(long interfaceTag) {
+ return InstanceIdentifier.builder(IfIndexesInterfaceMap.class).child(IfIndexInterface.class,
+ new IfIndexInterfaceKey((int) interfaceTag)).build();
+ }
+
+ public static String getNeutronPortNamefromPortFixedIp(DataBroker broker, String fixedIp) {
+ InstanceIdentifier id = buildFixedIpToPortNameIdentifier(fixedIp);
+ Optional<PortFixedipToPortName> portFixedipToPortNameData = read(broker, LogicalDatastoreType.CONFIGURATION,
+ id);
+ if (portFixedipToPortNameData.isPresent()) {
+ return portFixedipToPortNameData.get().getPortName();
+ }
+ return null;
+ }
+
+ private static InstanceIdentifier<PortFixedipToPortName> buildFixedIpToPortNameIdentifier(String fixedIp) {
+ InstanceIdentifier<PortFixedipToPortName> id = InstanceIdentifier.builder(NeutronPortData.class).child
+ (PortFixedipToPortName.class, new PortFixedipToPortNameKey(fixedIp)).build();
+ return id;
+ }
+
+ public static ElanTagName getElanInfoByElanTag(DataBroker broker,long elanTag) {
+ InstanceIdentifier<ElanTagName> elanId = getElanInfoEntriesOperationalDataPath(elanTag);
+ Optional<ElanTagName> existingElanInfo = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, elanId);
+ if(existingElanInfo.isPresent()) {
+ return existingElanInfo.get();
+ }
+ return null;
+ }
+
+ private static InstanceIdentifier<ElanTagName> getElanInfoEntriesOperationalDataPath(long elanTag) {
+ return InstanceIdentifier.builder(ElanTagNameMap.class).child(ElanTagName.class,
+ new ElanTagNameKey(elanTag)).build();
+ }
+
+
+ public static boolean isIpInSubnet(int ipAddress, String subnetCidr) {
+ String[] subSplit = subnetCidr.split("/");
+ if (subSplit.length < 2) {
+ return false;
+ }
+
+ String subnetStr = subSplit[0];
+ int subnet = 0;
+ try {
+ InetAddress subnetAddress = InetAddress.getByName(subnetStr);
+ subnet = Ints.fromByteArray(subnetAddress.getAddress());
+ } catch (Exception ex) {
+ LOG.error("Passed in Subnet IP string not convertible to InetAdddress " + subnetStr);
+ return false;
+ }
+ int prefixLength = Integer.valueOf(subSplit[1]);
+ int mask = -1 << (32 - prefixLength);
+ if ((subnet & mask) == (ipAddress & mask)) {
+ return true;
+ }
+ return false;
+ }
+
+ public static void removePrefixToInterfaceForVpnId(DataBroker broker, long vpnId) {
+ try {
+ // Clean up PrefixToInterface Operational DS
+ delete(broker, LogicalDatastoreType.OPERATIONAL,
+ InstanceIdentifier.builder(PrefixToInterface.class).child(VpnIds.class, new VpnIdsKey(vpnId)).build(),
+ DEFAULT_CALLBACK);
+ } catch (Exception e) {
+ LOG.error("Exception during cleanup of PrefixToInterface for VPN ID {}", vpnId, e);
+ }
+ }
+
+ public static void removeVpnExtraRouteForVpn(DataBroker broker, String vpnName) {
+ try {
+ // Clean up VPNExtraRoutes Operational DS
+ delete(broker, LogicalDatastoreType.OPERATIONAL,
+ InstanceIdentifier.builder(VpnToExtraroute.class).child(Vpn.class, new VpnKey(vpnName)).build(),
+ DEFAULT_CALLBACK);
+ } catch (Exception e) {
+ LOG.error("Exception during cleanup of VPNToExtraRoute for VPN {}", vpnName, e);
+ }
+ }
+
+ public static void removeVpnOpInstance(DataBroker broker, String vpnName) {
+ try {
+ // Clean up VPNInstanceOpDataEntry
+ delete(broker, LogicalDatastoreType.OPERATIONAL, getVpnInstanceOpDataIdentifier(vpnName),
+ DEFAULT_CALLBACK);
+ } catch (Exception e) {
+ LOG.error("Exception during cleanup of VPNInstanceOpDataEntry for VPN {}", vpnName, e);
+ }
+ }
+
+ public static void removeVpnInstanceToVpnId(DataBroker broker, String vpnName) {
+ try {
+ delete(broker, LogicalDatastoreType.CONFIGURATION, getVpnInstanceToVpnIdIdentifier(vpnName),
+ DEFAULT_CALLBACK);
+ } catch (Exception e) {
+ LOG.error("Exception during clean up of VpnInstanceToVpnId for VPN {}", vpnName, e);
+ }
+ }
+
+ public static void removeVrfTableForVpn(DataBroker broker, String vpnName) {
+ // Clean up FIB Entries Config DS
+ try {
+ delete(broker, LogicalDatastoreType.CONFIGURATION,
+ InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(vpnName)).build(),
+ DEFAULT_CALLBACK);
+ } catch (Exception e) {
+ LOG.error("Exception during clean up of VrfTable from FIB for VPN {}", vpnName, e);
+ }
+ }
+
+ public static void removeL3nexthopForVpnId(DataBroker broker, long vpnId) {
+ try {
+ // Clean up L3NextHop Operational DS
+ delete(broker, LogicalDatastoreType.OPERATIONAL,
+ InstanceIdentifier.builder(L3nexthop.class).child(VpnNexthops.class, new VpnNexthopsKey(vpnId)).build(),
+ DEFAULT_CALLBACK);
+ } catch (Exception e) {
+ LOG.error("Exception during cleanup of L3NextHop for VPN ID {}", vpnId, e);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice;
+
+import java.math.BigInteger;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.bgpmanager.api.IBgpManager;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationService;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+import org.opendaylight.fibmanager.api.IFibManager;
+import org.opendaylight.vpnmanager.api.IVpnManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
+import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilService;
+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.neutronvpn.rev150602.NeutronvpnService;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class VpnserviceProvider implements BindingAwareProvider, IVpnManager,
+ AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(VpnserviceProvider.class);
+ private VpnInterfaceManager vpnInterfaceManager;
+ private VpnManager vpnManager;
+ private IBgpManager bgpManager;
+ private IFibManager fibManager;
+ private IMdsalApiManager mdsalManager;
+ private OdlInterfaceRpcService interfaceManager;
+ private ItmRpcService itmProvider;
+ private IdManagerService idManager;
+ private OdlArputilService arpManager;
+ private NeutronvpnService neuService;
+ private PacketProcessingService m_packetProcessingService;
+ private SubnetRoutePacketInHandler subnetRoutePacketInHandler;
+ private NotificationService notificationService;
+
+ @Override
+ public void onSessionInitiated(ProviderContext session) {
+ LOG.info("VpnserviceProvider Session Initiated");
+ try {
+ final DataBroker dataBroker = session.getSALService(DataBroker.class);
+ vpnManager = new VpnManager(dataBroker, bgpManager);
+ vpnManager.setIdManager(idManager);
+ vpnInterfaceManager = new VpnInterfaceManager(dataBroker, bgpManager, notificationService);
+ vpnInterfaceManager.setMdsalManager(mdsalManager);
+ vpnInterfaceManager.setInterfaceManager(interfaceManager);
+ vpnInterfaceManager.setITMProvider(itmProvider);
+ vpnInterfaceManager.setIdManager(idManager);
+ vpnInterfaceManager.setArpManager(arpManager);
+ vpnInterfaceManager.setNeutronvpnManager(neuService);
+ //Handles subnet route entries
+ subnetRoutePacketInHandler = new SubnetRoutePacketInHandler(dataBroker, idManager);
+ m_packetProcessingService = session.getRpcService(PacketProcessingService.class);
+ subnetRoutePacketInHandler.setPacketProcessingService(m_packetProcessingService);
+ notificationService.registerNotificationListener(subnetRoutePacketInHandler);
+ vpnManager.setVpnInterfaceManager(vpnInterfaceManager);
+ createIdPool();
+
+ RouterInterfaceListener routerListener = new RouterInterfaceListener(dataBroker);
+ routerListener.setVpnInterfaceManager(vpnInterfaceManager);
+ } catch (Exception e) {
+ LOG.error("Error initializing services", e);
+ }
+ }
+
+ public void setNotificationService(NotificationService notificationService) {
+ this.notificationService = notificationService;
+ }
+
+ public void setBgpManager(IBgpManager bgpManager) {
+ LOG.debug("BGP Manager reference initialized");
+ this.bgpManager = bgpManager;
+ }
+
+ public void setMdsalManager(IMdsalApiManager mdsalManager) {
+ this.mdsalManager = mdsalManager;
+ }
+
+ public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
+ this.interfaceManager = interfaceManager;
+ }
+
+ public void setITMProvider(ItmRpcService itmProvider) {
+ this.itmProvider = itmProvider;
+ }
+
+ public void setIdManager(IdManagerService idManager) {
+ this.idManager = idManager;
+ }
+
+ public void setArpManager(OdlArputilService arpManager) {
+ this.arpManager = arpManager;
+ }
+
+ private void createIdPool() {
+ CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
+ .setPoolName(VpnConstants.VPN_IDPOOL_NAME)
+ .setLow(VpnConstants.VPN_IDPOOL_START)
+ .setHigh(new BigInteger(VpnConstants.VPN_IDPOOL_SIZE).longValue())
+ .build();
+ try {
+ Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
+ if ((result != null) && (result.get().isSuccessful())) {
+ LOG.debug("Created IdPool for VPN Service");
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Failed to create idPool for VPN Service",e);
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ vpnManager.close();
+ vpnInterfaceManager.close();
+
+ }
+
+ @Override
+ public void setFibService(IFibManager fibManager) {
+ LOG.debug("Fib service reference is initialized in VPN Manager");
+ this.fibManager = fibManager;
+ vpnInterfaceManager.setFibManager(fibManager);
+ }
+
+ @Override
+ public void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label) {
+ LOG.info("Adding extra route with destination {} and nexthop {}", destination, nextHop);
+ vpnInterfaceManager.addExtraRoute(destination, nextHop, rd, routerID, label, null);
+ }
+
+ @Override
+ public void delExtraRoute(String destination, String rd, String routerID) {
+ LOG.info("Deleting extra route with destination {}", destination);
+ vpnInterfaceManager.delExtraRoute(destination, rd, routerID);
+ }
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.utilities;
+
+import com.google.common.base.Optional;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.VpnUtil;
+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.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.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.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.ServicesInfo;
+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 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.OdlInterfaceRpcService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.DpnEndpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfoKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+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 InterfaceUtils {
+ private static final Logger LOG = LoggerFactory.getLogger(InterfaceUtils.class);
+ private static String OF_URI_SEPARATOR = ":";
+
+ public static BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
+ BigInteger nodeId = BigInteger.ZERO;
+ try {
+ GetDpidFromInterfaceInput
+ dpIdInput =
+ new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
+ Future<RpcResult<GetDpidFromInterfaceOutput>>
+ dpIdOutput =
+ interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
+ RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
+ if (dpIdResult.isSuccessful()) {
+ nodeId = dpIdResult.getResult().getDpid();
+ } else {
+ LOG.error("Could not retrieve DPN Id for interface {}", ifName);
+ }
+ } catch (NullPointerException | InterruptedException | ExecutionException e) {
+ LOG.error("Exception when getting dpn for interface {}", ifName, e);
+ }
+ return nodeId;
+ }
+
+ public static String getEndpointIpAddressForDPN(DataBroker broker, BigInteger dpnId) {
+ String nextHopIp = null;
+ InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
+ InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, new DPNTEPsInfoKey(dpnId)).build();
+ Optional<DPNTEPsInfo> tunnelInfo = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, tunnelInfoId);
+ if (tunnelInfo.isPresent()) {
+ List<TunnelEndPoints> nexthopIpList = tunnelInfo.get().getTunnelEndPoints();
+ if (nexthopIpList != null && !nexthopIpList.isEmpty()) {
+ nextHopIp = nexthopIpList.get(0).getIpAddress().getIpv4Address().getValue();
+ }
+ }
+ return nextHopIp;
+ }
+
+ 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();
+ }
+
+ 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 boolean isOperational(DataBroker dataBroker, String ifName) {
+ return getInterfaceStateFromOperDS(dataBroker, ifName) == null ? false : true;
+ }
+
+ public static InstanceIdentifier<Interface> buildStateInterfaceId(String interfaceName) {
+ InstanceIdentifier.InstanceIdentifierBuilder<Interface> idBuilder =
+ InstanceIdentifier.builder(InterfacesState.class)
+ .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class,
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName));
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> id = idBuilder.build();
+ return id;
+ }
+
+ public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceStateFromOperDS(DataBroker dataBroker, String interfaceName) {
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
+ buildStateInterfaceId(interfaceName);
+ Optional<Interface> ifStateOptional =
+ VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, ifStateId);
+ if (ifStateOptional.isPresent()) {
+ return ifStateOptional.get();
+ }
+
+ return null;
+ }
+
+ public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface getInterface(DataBroker broker, String interfaceName) {
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface> optInterface =
+ VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, getInterfaceIdentifier(interfaceName));
+ if(optInterface.isPresent()) {
+ return optInterface.get();
+ }
+ return null;
+ }
+
+ public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface> getInterfaceIdentifier(String interfaceName) {
+ return InstanceIdentifier.builder(Interfaces.class)
+ .child(
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface.class, new InterfaceKey(interfaceName)).build();
+ }
+
+ public static String getDpnFromNodeConnectorId(NodeConnectorId portId) {
+ /*
+ * NodeConnectorId is of form 'openflow:dpnid:portnum'
+ */
+ String[] split = portId.getValue().split(OF_URI_SEPARATOR);
+ return split[1];
+ }
+
+ public static BigInteger getDpIdFromInterface(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState) {
+ String lowerLayerIf = ifState.getLowerLayerIf().get(0);
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(lowerLayerIf);
+ return new BigInteger(getDpnFromNodeConnectorId(nodeConnectorId));
+ }
+
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnservice.impl.rev150216;
+
+import org.opendaylight.vpnservice.VpnserviceProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilService;
+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 VpnserviceImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnservice.impl.rev150216.AbstractVpnserviceImplModule {
+ public VpnserviceImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public VpnserviceImplModule(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.vpnservice.impl.rev150216.VpnserviceImplModule 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() {
+ IdManagerService idManager = getRpcregistryDependency().getRpcService(IdManagerService.class);
+ OdlArputilService arpManager = getRpcregistryDependency().getRpcService(OdlArputilService.class);
+ OdlInterfaceRpcService interfaceManager = getRpcregistryDependency().getRpcService(OdlInterfaceRpcService.class);
+ VpnserviceProvider provider = new VpnserviceProvider();
+ provider.setNotificationService(getNotificationServiceDependency());
+ provider.setBgpManager(getBgpmanagerDependency());
+ provider.setMdsalManager(getMdsalutilDependency());
+ provider.setInterfaceManager(interfaceManager);
+ provider.setIdManager(idManager);
+ provider.setArpManager(arpManager);
+ getBrokerDependency().registerProvider(provider);
+ return provider;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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
+ */
+/*
+* Generated file
+*
+* Generated from: yang module name: vpnservice yang module local name: vpnservice
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Fri Feb 13 17:27:11 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.vpnservice.impl.rev150216;
+public class VpnserviceImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpnservice.impl.rev150216.AbstractVpnserviceImplModuleFactory {
+
+}
--- /dev/null
+module vpnservice-impl {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:vpnservice:impl";
+ prefix "vpnservice-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 bgpmanager-api { prefix bgpmgr-api; revision-date 2015-04-20;}
+ import vpnmanager-api { prefix vpnmgr-api; revision-date 2015-05-08;}
+ import odl-mdsalutil { prefix odl-mdsal; revision-date 2015-04-10;}
+
+ description
+ "Service definition for vpnservice project";
+
+ revision "2015-02-16" {
+ description
+ "Initial revision";
+ }
+
+ identity vpnservice-impl {
+ base config:module-type;
+ config:provided-service vpnmgr-api:vpnmanager-api;
+ config:java-name-prefix VpnserviceImpl;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case vpnservice-impl {
+ when "/config:modules/config:module/config:type = 'vpnservice-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 bgpmanager {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity bgpmgr-api:bgpmanager-api;
+ }
+ }
+ }
+ container mdsalutil {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity odl-mdsal:odl-mdsalutil;
+ }
+ }
+ }
+ container notification-service {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity md-sal-binding-impl:binding-new-notification-service;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.test;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+class MockDataChangedEvent implements AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> {
+ Map<InstanceIdentifier<?>,DataObject> created = new HashMap<>();
+ Map<InstanceIdentifier<?>,DataObject> updated = new HashMap<>();
+ Map<InstanceIdentifier<?>,DataObject> original = new HashMap<>();
+ Set<InstanceIdentifier<?>> removed = new HashSet<>();
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getCreatedData() {
+ return created;
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getUpdatedData() {
+ return updated;
+ }
+
+ @Override
+ public Set<InstanceIdentifier<?>> getRemovedPaths() {
+ return removed;
+ }
+
+ @Override
+ public Map<InstanceIdentifier<?>, DataObject> getOriginalData() {
+ return original;
+ }
+
+ @Override
+ public DataObject getOriginalSubtree() {
+ throw new UnsupportedOperationException("Not implemented by mock");
+ }
+
+ @Override
+ public DataObject getUpdatedSubtree() {
+ throw new UnsupportedOperationException("Not implemented by mock");
+ }
+}
--- /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.test;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+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.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.SubnetOpDpnManager;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.PortOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.SubnetOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.port.op.data.PortOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.port.op.data.PortOpDataEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.port.op.data.PortOpDataEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpnKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.subnet.to.dpn.VpnInterfaces;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+
+
+
+@RunWith(MockitoJUnitRunner.class)
+public class SubnetOpDpnManagerTest {
+
+ BigInteger dpId = BigInteger.valueOf(1);
+ Uuid subnetId = Uuid.getDefaultInstance("067e6162-3b6f-4ae2-a171-2470b63dff00");
+ String infName = "VPN";
+ SubnetToDpn subnetToDpn = null;
+ PortOpDataEntry portOp = null;
+ String portId = "abc";
+
+ InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
+ child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
+ InstanceIdentifier<SubnetToDpn> dpnOpId = subOpIdentifier.child(SubnetToDpn.class, new SubnetToDpnKey(dpId));
+ InstanceIdentifier<PortOpDataEntry> portOpIdentifier = InstanceIdentifier.builder(PortOpData.class).
+ child(PortOpDataEntry.class, new PortOpDataEntryKey(infName)).build();
+
+ @Mock DataBroker dataBroker;
+ @Mock ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
+ @Mock ReadOnlyTransaction mockReadTx;
+ @Mock WriteTransaction mockWriteTx;
+
+ SubnetOpDpnManager subOpDpnManager;
+
+ Optional<SubnetToDpn> optionalSubDpn;
+ Optional<PortOpDataEntry> optionalPortOp;
+
+ @Before
+ public void setUp() throws Exception {
+ when(dataBroker.registerDataChangeListener(
+ any(LogicalDatastoreType.class),
+ any(InstanceIdentifier.class),
+ any(DataChangeListener.class),
+ any(AsyncDataBroker.DataChangeScope.class)))
+ .thenReturn(dataChangeListenerRegistration);
+ setupMocks();
+
+ subOpDpnManager = new SubnetOpDpnManager(dataBroker);
+
+ optionalSubDpn = Optional.of(subnetToDpn);
+ optionalPortOp = Optional.of(portOp);
+
+ doReturn(Futures.immediateCheckedFuture(optionalPortOp)).when(mockReadTx).read(LogicalDatastoreType
+ .OPERATIONAL, portOpIdentifier);
+ doReturn(Futures.immediateCheckedFuture(optionalSubDpn)).when(mockReadTx).read(LogicalDatastoreType
+ .OPERATIONAL, dpnOpId);
+
+ }
+
+ private void setupMocks() {
+
+ List<VpnInterfaces> vpnInterfaces = new ArrayList<>();
+ subnetToDpn = new SubnetToDpnBuilder().setDpnId(dpId).setKey(new SubnetToDpnKey(dpId)).setVpnInterfaces
+ (vpnInterfaces).build();
+ portOp = new PortOpDataEntryBuilder().setDpnId(dpId).setKey(new PortOpDataEntryKey(infName)).setSubnetId
+ (subnetId).setPortId(portId).build();
+ doReturn(mockReadTx).when(dataBroker).newReadOnlyTransaction();
+ doReturn(mockWriteTx).when(dataBroker).newWriteOnlyTransaction();
+ doReturn(Futures.immediateCheckedFuture(null)).when(mockWriteTx).submit();
+ }
+
+ @Test
+ public void testAddInterfaceToDpn() {
+
+ subOpDpnManager.addInterfaceToDpn(subnetId, dpId, infName);
+
+ verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, dpnOpId, subnetToDpn, true);
+
+ }
+
+ @Test
+ public void testAddPortOpDataEntryPortOpPresent() {
+
+ subOpDpnManager.addPortOpDataEntry(infName, subnetId, dpId);
+
+ verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, portOpIdentifier, portOp, true);
+ }
+
+ @Test
+ public void testAddPortOpDataEntryPortOpAbsent() {
+
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(LogicalDatastoreType
+ .OPERATIONAL, portOpIdentifier);
+
+ subOpDpnManager.addPortOpDataEntry(infName, subnetId, dpId);
+
+ verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, portOpIdentifier, portOp, true);
+ }
+
+ @Test
+ public void testRemoveInterfaceFromDpn() {
+
+ subOpDpnManager.removeInterfaceFromDpn(subnetId, dpId, infName);
+
+ verify(mockWriteTx).delete(LogicalDatastoreType.OPERATIONAL, dpnOpId);
+ }
+
+ @Test
+ public void testRemovePortOpDataEntryPortOpPresent() {
+
+ subOpDpnManager.removePortOpDataEntry(infName);
+
+ verify(mockWriteTx).delete(LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
+ }
+
+ @Test
+ public void testRemovePortOpDataEntryPortOpAbsent() {
+
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(LogicalDatastoreType
+ .OPERATIONAL, portOpIdentifier);
+
+ subOpDpnManager.removePortOpDataEntry(infName);
+
+ verify(mockReadTx).read(LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
+
+ }
+
+ @Test
+ public void testGetPortOpDataEntryPortOpPresent() {
+
+ subOpDpnManager.getPortOpDataEntry(infName);
+
+ verify(mockReadTx).read(LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
+
+ }
+
+ @Test
+ public void testGetPortOpDataEntryPortOpAbsent() {
+
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(LogicalDatastoreType
+ .OPERATIONAL, portOpIdentifier);
+
+ subOpDpnManager.getPortOpDataEntry(infName);
+
+ verify(mockReadTx).read(LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
+
+ }
+
+}
--- /dev/null
+/*
+ * 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.vpnservice.test;
+
+import static org.junit.Assert.*;
+import static org.mockito.Matchers.*;
+import static org.mockito.Mockito.when;
+
+import org.junit.*;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.vpnservice.VpnManager;
+import org.opendaylight.bgpmanager.api.IBgpManager;
+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.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTargetKey;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4Family;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+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.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.*;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.*;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.apply.label.apply.label.mode.*;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.apply.label.ApplyLabelMode;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.ApplyLabelBuilder;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4FamilyBuilder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(MockitoJUnitRunner.class)
+public class VpnServiceTest {
+ @Mock DataBroker dataBroker;
+ @Mock IBgpManager bgpManager;
+ @Mock ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
+ MockDataChangedEvent event;
+
+ @Before
+ public void setUp() throws Exception {
+ when(dataBroker.registerDataChangeListener(
+ any(LogicalDatastoreType.class),
+ any(InstanceIdentifier.class),
+ any(DataChangeListener.class),
+ any(DataChangeScope.class)))
+ .thenReturn(dataChangeListenerRegistration);
+ event = new MockDataChangedEvent();
+ }
+
+ @Test
+ public void test() {
+
+ List<VpnTarget> vpnTargetList = new ArrayList<VpnTarget>();
+
+ VpnTarget vpneRTarget = new VpnTargetBuilder().setKey(new VpnTargetKey("100:1")).setVrfRTValue("100:1")
+ .setVrfRTType(VpnTarget.VrfRTType.ExportExtcommunity).build();
+ VpnTarget vpniRTarget = new VpnTargetBuilder().setKey(new VpnTargetKey("100:2")).setVrfRTValue("100:2")
+ .setVrfRTType(VpnTarget.VrfRTType.ImportExtcommunity).build();
+
+ vpnTargetList.add(vpneRTarget);
+ vpnTargetList.add(vpniRTarget);
+
+ VpnTargets vpnTargets = new VpnTargetsBuilder().setVpnTarget(vpnTargetList).build();
+
+ Ipv4Family ipv4Family = new Ipv4FamilyBuilder().setRouteDistinguisher("100:1").setVpnTargets(vpnTargets)
+ .setApplyLabel(new ApplyLabelBuilder().setApplyLabelMode(
+ new PerRouteBuilder().setApplyLabelPerRoute(true).build()).build()).build();
+
+ VpnInstanceBuilder builder = new VpnInstanceBuilder().setKey(new VpnInstanceKey("Vpn1")).setIpv4Family
+ (ipv4Family);
+ VpnInstance instance = builder.build();
+ VpnManager vpnManager = new VpnManager(dataBroker, bgpManager);
+ event.created.put(createVpnId("Vpn1"), instance);
+ //TODO: Need to enhance the test case to handle ds read/write ops
+ //vpnManager.onDataChanged(event);
+ }
+
+ private InstanceIdentifier<VpnInstance> createVpnId(String name) {
+ InstanceIdentifierBuilder<VpnInstance> idBuilder =
+ InstanceIdentifier.builder(VpnInstances.class).child(VpnInstance.class, new VpnInstanceKey(name));
+ InstanceIdentifier<VpnInstance> id = idBuilder.build();
+ return id;
+ }
+
+}
--- /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.test;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.bgpmanager.api.IBgpManager;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+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.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.VpnInterfaceManager;
+import org.opendaylight.vpnservice.VpnSubnetRouteHandler;
+import org.opendaylight.vpnservice.interfacemgr.globals.IfmConstants;
+import org.opendaylight.vpnservice.utilities.InterfaceUtils;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance.Ipv4Family;
+import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.vpn.instance
+ .Ipv4FamilyBuilder;
+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.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.PortOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.PortOpDataBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.SubnetOpData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.RdToElanOp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstanceToVpnId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.TaskState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.port.op.data.PortOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.port.op.data.PortOpDataEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.port.op.data.PortOpDataEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.rd.to.elan.op.RdToElanOpEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.rd.to.elan.op.RdToElanOpEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.rd.to.elan.op.RdToElanOpEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.SubnetOpDataEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.SubnetToDpnKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.subnet.to.dpn.VpnInterfaces;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.subnet.to.dpn.VpnInterfacesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.subnet.op.data.subnet.op.data.entry.subnet.to.dpn.VpnInterfacesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey;
+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;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.DpnEndpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfo;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfoBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.DPNTEPsInfoKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.op.rev150701.dpn.endpoints.dpn.teps.info.TunnelEndPointsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.PortAddedToSubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.PortRemovedFromSubnet;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.PortAddedToSubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.PortRemovedFromSubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.SubnetAddedToVpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.SubnetUpdatedInVpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.SubnetDeletedFromVpn;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.SubnetAddedToVpnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.SubnetUpdatedInVpnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.SubnetDeletedFromVpnBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.Subnetmaps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.Subnetmap;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.SubnetmapBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.subnetmaps.SubnetmapKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class VpnSubnetRouteHandlerTest {
+
+ BigInteger dpId = BigInteger.valueOf(1);
+ PortAddedToSubnet portAddedToSubnet = null;
+ PortRemovedFromSubnet portRemovedFromSubnet = null;
+ SubnetAddedToVpn subnetAddedToVpn = null;
+ SubnetUpdatedInVpn subnetUpdatedInVpn = null;
+ SubnetDeletedFromVpn subnetDeletedFromVpn = null;
+ SubnetToDpn subnetToDpn = null;
+ RdToElanOpEntry rdToElanOpEntry = null;
+ String subnetIp = "10.1.1.24";
+ String routeDistinguisher = "100:1";
+ String nexthopIp = null;
+ String poolName = null;
+ String interfaceName = "VPN";
+ Uuid subnetId = Uuid.getDefaultInstance("067e6162-3b6f-4ae2-a171-2470b63dff00");
+ Uuid portId = Uuid.getDefaultInstance("54947df8-0e9e-4471-a2f9-9af509fb5889");
+ Uuid tenantId = Uuid.getDefaultInstance("54947df8-0e9e-4571-a2f9-9af509fb5889");
+ String portKey = portId.getValue();
+ Long elanTag = null;
+ Long longId = null;
+ PortOpDataEntry portOp = null;
+ PortOpData portOpData = null;
+ SubnetOpDataEntry subnetOp = null;
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface
+ stateInterface;
+ List<String> lowerLayerIfList = new ArrayList<>();
+ NodeConnectorId nodeConnectorId = null;
+ VpnInterfaces vpnIntfaces = null;
+ VpnInstance vpnInstance = null;
+ Subnetmap subnetmap = null;
+ DPNTEPsInfo dpntePsInfo = null;
+ TunnelEndPoints tunlEndPts = null;
+ IpAddress ipAddress = null;
+ Ipv4Family ipv4Family = null;
+ String idKey = null;
+ AllocateIdOutput allocateIdOutput = null;
+ AllocateIdInput allocateIdInput = null;
+ org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance vpnInstnce;
+
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces
+ .state.Interface> ifStateId = InterfaceUtils.buildStateInterfaceId(portKey);
+ InstanceIdentifier<SubnetOpDataEntry> subOpIdentifier = InstanceIdentifier.builder(SubnetOpData.class).
+ child(SubnetOpDataEntry.class, new SubnetOpDataEntryKey(subnetId)).build();
+ InstanceIdentifier<SubnetToDpn> dpnOpId = subOpIdentifier.child(SubnetToDpn.class, new SubnetToDpnKey(dpId));
+ InstanceIdentifier<DPNTEPsInfo> tunnelInfoId =
+ InstanceIdentifier.builder(DpnEndpoints.class).child(DPNTEPsInfo.class, new DPNTEPsInfoKey(dpId)).build();
+ InstanceIdentifier<PortOpDataEntry> portOpIdentifier = InstanceIdentifier.builder(PortOpData.class).
+ child(PortOpDataEntry.class, new PortOpDataEntryKey(portKey)).build();
+ InstanceIdentifier<PortOpDataEntry> instPortOp = InstanceIdentifier.builder(PortOpData.class).
+ child(PortOpDataEntry.class, new PortOpDataEntryKey(interfaceName)).build();
+ InstanceIdentifier<Subnetmap> subMapid = InstanceIdentifier.builder(Subnetmaps.class).child(Subnetmap.class, new
+ SubnetmapKey(subnetId)).build();
+ InstanceIdentifier<PortOpData> portOpIdentifr = InstanceIdentifier.builder(PortOpData.class).build();
+ InstanceIdentifier<RdToElanOpEntry> rdIdentifier = InstanceIdentifier.builder(RdToElanOp.class).
+ child(RdToElanOpEntry.class, new RdToElanOpEntryKey(interfaceName, subnetIp)).build();
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id
+ .VpnInstance> instVpnInstance = getVpnInstanceToVpnIdIdentifier(interfaceName);
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.
+ VpnInstance> vpnInstanceIdentifier = InstanceIdentifier.builder(VpnInstances.class).child(org.opendaylight
+ .yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance.class,
+ new org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances
+ .VpnInstanceKey(interfaceName)).build();
+
+ @Mock DataBroker dataBroker;
+ @Mock ListenerRegistration<DataChangeListener> dataChangeListenerRegistration;
+ @Mock ReadOnlyTransaction mockReadTx;
+ @Mock WriteTransaction mockWriteTx;
+ @Mock IBgpManager bgpManager;
+ @Mock VpnInterfaceManager vpnInterfaceManager;
+ @Mock IdManagerService idManager;
+
+ VpnSubnetRouteHandler vpnSubnetRouteHandler;
+
+ Optional<Interface> optionalIfState;
+ Optional<SubnetOpDataEntry> optionalSubs;
+ Optional<SubnetToDpn> optionalSubDpn;
+ Optional<DPNTEPsInfo> optionalTunnelInfo;
+ Optional<PortOpDataEntry> optionalPortOp;
+ Optional<PortOpData> optionalPtOp;
+ Optional<Subnetmap> optionalSubnetMap;
+ Optional<RdToElanOpEntry> optionalRd;
+ Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
+ optionalVpnInstnce;
+ Optional<org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance>
+ vpnInstanceOptional;
+
+ @Before
+ public void setUp() throws Exception {
+ when(dataBroker.registerDataChangeListener(
+ any(LogicalDatastoreType.class),
+ any(InstanceIdentifier.class),
+ any(DataChangeListener.class),
+ any(AsyncDataBroker.DataChangeScope.class)))
+ .thenReturn(dataChangeListenerRegistration);
+ setupMocks();
+
+ vpnSubnetRouteHandler = new VpnSubnetRouteHandler(dataBroker, bgpManager, vpnInterfaceManager);
+ vpnSubnetRouteHandler.setIdManager(idManager);
+ Future<RpcResult<AllocateIdOutput>> idOutputOptional = RpcResultBuilder.success(allocateIdOutput).buildFuture();
+
+ optionalIfState = Optional.of(stateInterface);
+ optionalSubs = Optional.of(subnetOp);
+ optionalSubDpn = Optional.of(subnetToDpn);
+ optionalTunnelInfo = Optional.of(dpntePsInfo);
+ optionalPortOp = Optional.of(portOp);
+ optionalPtOp = Optional.of(portOpData);
+ optionalSubnetMap = Optional.of(subnetmap);
+ optionalRd = Optional.of(rdToElanOpEntry);
+ optionalVpnInstnce = Optional.of(vpnInstance);
+ vpnInstanceOptional = Optional.of(vpnInstnce);
+
+ doReturn(Futures.immediateCheckedFuture(optionalRd)).when(mockReadTx).read(LogicalDatastoreType.OPERATIONAL,
+ rdIdentifier);
+ doReturn(Futures.immediateCheckedFuture(optionalIfState)).when(mockReadTx).read(LogicalDatastoreType
+ .OPERATIONAL, ifStateId);
+ doReturn(Futures.immediateCheckedFuture(optionalSubs)).when(mockReadTx).read(LogicalDatastoreType
+ .OPERATIONAL, subOpIdentifier);
+ doReturn(Futures.immediateCheckedFuture(optionalSubDpn)).when(mockReadTx).read(LogicalDatastoreType
+ .OPERATIONAL, dpnOpId);
+ doReturn(Futures.immediateCheckedFuture(optionalTunnelInfo)).when(mockReadTx).read(LogicalDatastoreType
+ .CONFIGURATION, tunnelInfoId);
+ doReturn(Futures.immediateCheckedFuture(optionalPortOp)).when(mockReadTx).read(LogicalDatastoreType
+ .OPERATIONAL, portOpIdentifier);
+ doReturn(Futures.immediateCheckedFuture(optionalPtOp)).when(mockReadTx).read(LogicalDatastoreType
+ .OPERATIONAL, portOpIdentifr);
+ doReturn(Futures.immediateCheckedFuture(optionalPortOp)).when(mockReadTx).read(LogicalDatastoreType
+ .OPERATIONAL, instPortOp);
+ doReturn(Futures.immediateCheckedFuture(optionalSubnetMap)).when(mockReadTx).read(LogicalDatastoreType
+ .CONFIGURATION, subMapid);
+ doReturn(Futures.immediateCheckedFuture(optionalVpnInstnce)).when(mockReadTx).read(LogicalDatastoreType
+ .CONFIGURATION, instVpnInstance);
+ doReturn(Futures.immediateCheckedFuture(vpnInstanceOptional)).when(mockReadTx).read(LogicalDatastoreType
+ .CONFIGURATION,vpnInstanceIdentifier);
+ doReturn(idOutputOptional).when(idManager).allocateId(allocateIdInput);
+ }
+
+ private void setupMocks() {
+
+ nexthopIp = "10.1.1.25";
+ idKey = "100:1.10.1.1.24";
+ poolName = "vpnservices";
+ elanTag = Long.valueOf(2);
+ longId = Long.valueOf("100");
+ nodeConnectorId = buildNodeConnectorId(dpId, Long.valueOf(2));
+ ipAddress = IpAddressBuilder.getDefaultInstance(nexthopIp);
+ vpnIntfaces = new VpnInterfacesBuilder().setInterfaceName(interfaceName).setKey(new VpnInterfacesKey
+ (interfaceName)).build();
+ List<VpnInterfaces> vpnInterfaces = new ArrayList<>();
+ List<SubnetToDpn> subToDpn = new ArrayList<>();
+ List<Uuid> portList = new ArrayList<>();
+ List<PortOpDataEntry> listPortOpDataEntry = new ArrayList<>();
+ List<TunnelEndPoints> tunnelEndPoints = new ArrayList<>();
+ vpnInterfaces.add(vpnIntfaces);
+ lowerLayerIfList.add(nodeConnectorId.getValue());
+ portOp = new PortOpDataEntryBuilder().setDpnId(dpId).setKey(new PortOpDataEntryKey(tenantId.getValue()))
+ .setSubnetId(subnetId).setPortId(tenantId.getValue()).build();
+ subnetToDpn = new SubnetToDpnBuilder().setDpnId(dpId).setKey(new SubnetToDpnKey(dpId)).setVpnInterfaces
+ (vpnInterfaces).build();
+ allocateIdOutput = new AllocateIdOutputBuilder().setIdValue(longId).build();
+ allocateIdInput = new AllocateIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
+ subToDpn.add(subnetToDpn);
+ portList.add(portId);
+ listPortOpDataEntry.add(portOp);
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state
+ .InterfaceBuilder ifaceBuilder = new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf
+ .interfaces.rev140508.interfaces.state.InterfaceBuilder();
+ ifaceBuilder.setLowerLayerIf(lowerLayerIfList).setType(L2vlan.class)
+ .setAdminStatus(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508
+ .interfaces.state.Interface.AdminStatus.Up).setOperStatus(Interface.OperStatus.Up)
+ .setIfIndex(100).setKey(new InterfaceKey(interfaceName)).setName(interfaceName)
+ .setPhysAddress(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715
+ .PhysAddress.getDefaultInstance("AA:AA:AA:AA:AA:AA"));
+ stateInterface = ifaceBuilder.build();
+ portAddedToSubnet = new PortAddedToSubnetBuilder().setSubnetIp(subnetIp).setPortId(portId).setSubnetId
+ (subnetId).setElanTag(elanTag).build();
+ portRemovedFromSubnet = new PortRemovedFromSubnetBuilder().setPortId(portId).setSubnetId(subnetId)
+ .setSubnetIp(subnetIp).setElanTag(elanTag).build();
+ subnetAddedToVpn = new SubnetAddedToVpnBuilder().setElanTag(elanTag).setSubnetId(subnetId).setVpnName
+ (interfaceName).setExternalVpn(true).setSubnetIp(subnetIp).build();
+ subnetUpdatedInVpn = new SubnetUpdatedInVpnBuilder().setElanTag(elanTag).setSubnetIp(subnetIp).setSubnetId
+ (subnetId).setVpnName(interfaceName).setExternalVpn(false).build();
+ subnetDeletedFromVpn = new SubnetDeletedFromVpnBuilder().setExternalVpn(true).setSubnetId(subnetId)
+ .setSubnetIp(subnetIp).setVpnName(interfaceName).setElanTag(elanTag).build();
+ subnetOp = new SubnetOpDataEntryBuilder().setElanTag(elanTag).setNhDpnId(dpId).setSubnetCidr(subnetIp)
+ .setSubnetId(subnetId).setKey(new SubnetOpDataEntryKey(subnetId)).setVpnName(interfaceName)
+ .setVrfId(routeDistinguisher).setSubnetToDpn(subToDpn).setRouteAdvState(TaskState.Done).build();
+ vpnInstance = new VpnInstanceBuilder().setVpnId(elanTag).setVpnInstanceName(interfaceName).setVrfId
+ (interfaceName).setKey(new VpnInstanceKey(interfaceName)).build();
+ subnetmap = new SubnetmapBuilder().setSubnetIp(subnetIp).setId(subnetId).setNetworkId(portId).setKey(new
+ SubnetmapKey(subnetId)).setRouterId(portId).setVpnId(subnetId)
+ .setTenantId(tenantId).setPortList(portList).build();
+ portOpData = new PortOpDataBuilder().setPortOpDataEntry(listPortOpDataEntry).build();
+ dpntePsInfo = new DPNTEPsInfoBuilder().setDPNID(dpId).setUp(true).setKey(new DPNTEPsInfoKey(dpId))
+ .setTunnelEndPoints(tunnelEndPoints).build();
+ tunlEndPts = new TunnelEndPointsBuilder().setInterfaceName(interfaceName).setVLANID(10).setIpAddress
+ (ipAddress).build();
+ tunnelEndPoints.add(tunlEndPts);
+ rdToElanOpEntry = new RdToElanOpEntryBuilder().setElanTag(elanTag).setRd(interfaceName).setVpnName
+ (interfaceName).setNextHopIp(nexthopIp)
+ .setKey(new RdToElanOpEntryKey(interfaceName, subnetIp)).setSubnetIp(subnetIp).build();
+ ipv4Family = new Ipv4FamilyBuilder().setRouteDistinguisher(routeDistinguisher).build();
+ vpnInstnce = new org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances
+ .VpnInstanceBuilder().setKey(new org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn
+ .rev140815.vpn.instances.VpnInstanceKey(interfaceName)).setVpnInstanceName(interfaceName)
+ .setIpv4Family(ipv4Family).build();
+ doReturn(mockReadTx).when(dataBroker).newReadOnlyTransaction();
+ doReturn(mockWriteTx).when(dataBroker).newWriteOnlyTransaction();
+ doReturn(Futures.immediateCheckedFuture(null)).when(mockWriteTx).submit();
+
+ }
+
+ @Test
+ public void testOnPortAddedToSubnet() {
+
+ vpnSubnetRouteHandler.onPortAddedToSubnet(portAddedToSubnet);
+
+ verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, portOpIdentifier, portOp, true);
+ verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, dpnOpId, subnetToDpn, true);
+ verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subnetOp, true);
+ }
+
+ @Test
+ public void testOnPortRemovedFromSubnet() {
+
+ vpnSubnetRouteHandler.onPortRemovedFromSubnet(portRemovedFromSubnet);
+
+ verify(mockWriteTx).delete(LogicalDatastoreType.OPERATIONAL, portOpIdentifier);
+ verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, dpnOpId, subnetToDpn, true);
+ verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subnetOp, true);
+
+ }
+
+ @Test
+ public void testOnInterfaceUp() {
+
+ vpnSubnetRouteHandler.onInterfaceUp(stateInterface);
+
+ verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, instPortOp, portOp, true);
+ verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, dpnOpId, subnetToDpn, true);
+ verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subnetOp, true);
+ }
+
+ @Test
+ public void testOnInterfaceDown() {
+
+ vpnSubnetRouteHandler.onInterfaceDown(stateInterface);
+
+ verify(mockWriteTx).delete(LogicalDatastoreType.OPERATIONAL, dpnOpId);
+ verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subnetOp, true);
+
+ }
+
+ @Test
+ public void testOnSubnetAddedToVpn() {
+
+ doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(LogicalDatastoreType
+ .OPERATIONAL, subOpIdentifier);
+
+ vpnSubnetRouteHandler.onSubnetAddedToVpn(subnetAddedToVpn);
+
+ verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, dpnOpId, subnetToDpn, true);
+ verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, portOpIdentifier, portOp, true);
+ verify(mockWriteTx).put(LogicalDatastoreType.OPERATIONAL, subOpIdentifier, subnetOp, true);
+
+
+ }
+
+ @Test
+ public void testOnSubnetUpdatedInVpn() {
+
+ vpnSubnetRouteHandler.onSubnetUpdatedInVpn(subnetUpdatedInVpn);
+
+ verify(mockWriteTx).delete(LogicalDatastoreType.OPERATIONAL, instPortOp);
+ verify(mockWriteTx).delete(LogicalDatastoreType.OPERATIONAL, subOpIdentifier);
+
+ }
+
+ @Test
+ public void testOnSubnetDeletedFromVpn() {
+
+ vpnSubnetRouteHandler.onSubnetDeletedFromVpn(subnetDeletedFromVpn);
+
+ verify(mockWriteTx).delete(LogicalDatastoreType.OPERATIONAL, instPortOp);
+ verify(mockWriteTx).delete(LogicalDatastoreType.OPERATIONAL, subOpIdentifier);
+
+ }
+
+ public static NodeConnectorId buildNodeConnectorId(BigInteger dpn, long portNo) {
+ return new NodeConnectorId(buildNodeConnectorString(dpn, portNo));
+ }
+
+ public static String buildNodeConnectorString(BigInteger dpn, long portNo) {
+ return new StringBuffer().append(IfmConstants.OF_URI_PREFIX).append(dpn)
+ .append(IfmConstants.OF_URI_SEPARATOR).append(portNo).toString();
+ }
+
+ public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to
+ .vpn.id.VpnInstance> getVpnInstanceToVpnIdIdentifier(String vpnName) {
+ return InstanceIdentifier.builder(VpnInstanceToVpnId.class).child(org.opendaylight.yang.gen.v1.urn
+ .opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance.class,
+ new org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
+ }
+
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 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">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.opendaylight.odlparent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>1.7.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.opendaylight.vpnservice</groupId>
+ <artifactId>vpnservice-artifacts</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>vpnservice-features</artifactId>
+ <version>${project.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>