org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelAddWorker.java Source code

Java tutorial

Introduction

Here is the source code for org.opendaylight.genius.itm.confighelpers.ItmExternalTunnelAddWorker.java

Source

/*
 * Copyright (c) 2016, 2017 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */
package org.opendaylight.genius.itm.confighelpers;

import com.google.common.base.Optional;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.ListenableFuture;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.net.util.SubnetUtils;
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.genius.itm.globals.ITMConstants;
import org.opendaylight.genius.itm.impl.ItmUtils;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.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.genius.idmanager.rev160406.IdManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeBase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeVxlan;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.TunnelEndPoints;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.dpn.teps.info.tunnel.end.points.TzMembership;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnelKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.TransportZones;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZone;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.TransportZoneKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.Subnets;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.DeviceVteps;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rev160406.transport.zones.transport.zone.subnets.Vteps;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ItmExternalTunnelAddWorker {
    private static final Logger LOG = LoggerFactory.getLogger(ItmExternalTunnelAddWorker.class);

    private static Boolean monitorEnabled;
    private static Integer monitorInterval;
    private static Class<? extends TunnelMonitoringTypeBase> monitorProtocol;

    private static final FutureCallback<Void> DEFAULT_CALLBACK = new FutureCallback<Void>() {
        @Override
        public void onSuccess(Void result) {
            LOG.debug("Success in Datastore operation");
        }

        @Override
        public void onFailure(Throwable error) {
            LOG.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 transaction = 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,
                        new String(firstEndPt.getIpAddress().getValue()), new String(extIp.getValue()), tunTypeStr);
                char[] subnetMaskArray = firstEndPt.getSubnetMask().getValue();
                boolean useOfTunnel = ItmUtils.falseIfNull(firstEndPt.isOptionOfTunnel());
                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();
                LOG.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, ITMConstants.DEFAULT_MONITOR_PROTOCOL, null, useOfTunnel);

                LOG.debug(" Trunk Interface builder - {} ", iface);
                InstanceIdentifier<Interface> trunkIdentifier = ItmUtils.buildId(trunkInterfaceName);
                LOG.debug(" Trunk Interface Identifier - {} ", trunkIdentifier);
                LOG.trace(" Writing Trunk Interface to Config DS {}, {} ", trunkIdentifier, iface);
                transaction.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);
                transaction.merge(LogicalDatastoreType.CONFIGURATION, path, tnl, true);
            }
            futures.add(transaction.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 writeTransaction = dataBroker.newWriteOnlyTransaction();
        monitorInterval = ITMConstants.BFD_DEFAULT_MONITOR_INTERVAL;
        monitorProtocol = ITMConstants.DEFAULT_MONITOR_PROTOCOL;
        monitorEnabled = ItmUtils.readMonitoringStateFromCache(dataBroker);
        if (null != cfgdDpnList && !cfgdDpnList.isEmpty()) {
            LOG.trace("calling tunnels from css {}", cfgdDpnList);
            tunnelsFromCSS(cfgdDpnList, idManagerService, futures, writeTransaction, dataBroker);
        }
        if (null != cfgdHwVteps && !cfgdHwVteps.isEmpty()) {
            LOG.trace("calling tunnels from hwTep {}", cfgdHwVteps);
            tunnelsFromhWVtep(cfgdHwVteps, idManagerService, futures, writeTransaction, dataBroker);
        }

        if (cfgdDpnList != null && !cfgdDpnList.isEmpty() || cfgdHwVteps != null && !cfgdHwVteps.isEmpty()) {
            futures.add(writeTransaction.submit());
        }
        return futures;
    }

    private static void tunnelsFromCSS(List<DPNTEPsInfo> cfgdDpnList, IdManagerService idManagerService,
            List<ListenableFuture<Void>> futures, WriteTransaction transaction, DataBroker dataBroker) {
        Boolean monitorEnabled = ItmUtils.readMonitoringStateFromCache(dataBroker);
        Class<? extends TunnelMonitoringTypeBase> monitorProtocol = ITMConstants.DEFAULT_MONITOR_PROTOCOL;
        for (DPNTEPsInfo dpn : cfgdDpnList) {
            LOG.trace("processing dpn {}", dpn);
            if (dpn.getTunnelEndPoints() != null && !dpn.getTunnelEndPoints().isEmpty()) {
                for (TunnelEndPoints tep : dpn.getTunnelEndPoints()) {
                    for (TzMembership zone : tep.getTzMembership()) {
                        createTunnelsFromOVSinTransportZone(zone.getZoneName(), dpn, tep, idManagerService, futures,
                                transaction, dataBroker);
                    }
                }
            }
        }
    }

    private static void createTunnelsFromOVSinTransportZone(String zoneName, DPNTEPsInfo dpn, TunnelEndPoints tep,
            IdManagerService idManagerService, List<ListenableFuture<Void>> futures, WriteTransaction transaction,
            DataBroker dataBroker) {
        InstanceIdentifier<TransportZone> tzonePath = InstanceIdentifier.builder(TransportZones.class)
                .child(TransportZone.class, new TransportZoneKey(zoneName)).build();
        Optional<TransportZone> transportZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION, tzonePath,
                dataBroker);
        if (transportZoneOptional.isPresent()) {
            TransportZone transportZone = transportZoneOptional.get();
            //do we need to check tunnel type?
            if (transportZone.getSubnets() != null && !transportZone.getSubnets().isEmpty()) {
                for (Subnets sub : transportZone.getSubnets()) {
                    if (sub.getDeviceVteps() != null && !sub.getDeviceVteps().isEmpty()) {
                        for (DeviceVteps hwVtepDS : sub.getDeviceVteps()) {
                            //dont mesh if hwVteps and OVS-tep have same ip-address
                            if (hwVtepDS.getIpAddress().equals(tep.getIpAddress())) {
                                continue;
                            }
                            final String cssID = dpn.getDPNID().toString();
                            String nodeId = hwVtepDS.getNodeId();
                            boolean useOfTunnel = ItmUtils.falseIfNull(tep.isOptionOfTunnel());
                            LOG.trace("wire up {} and {}", tep, hwVtepDS);
                            if (!wireUp(dpn.getDPNID(), tep.getPortname(), sub.getVlanId(), tep.getIpAddress(),
                                    useOfTunnel, nodeId, hwVtepDS.getIpAddress(), tep.getSubnetMask(),
                                    sub.getGatewayIp(), sub.getPrefix(), transportZone.getTunnelType(), false,
                                    monitorProtocol, monitorInterval, idManagerService, dataBroker, futures,
                                    transaction)) {
                                LOG.error("Unable to build tunnel {} -- {}", tep.getIpAddress(),
                                        hwVtepDS.getIpAddress());
                            }
                            //TOR-OVS
                            LOG.trace("wire up {} and {}", hwVtepDS, tep);
                            if (!wireUp(hwVtepDS.getTopologyId(), hwVtepDS.getNodeId(), hwVtepDS.getIpAddress(),
                                    cssID, tep.getIpAddress(), sub.getPrefix(), sub.getGatewayIp(),
                                    tep.getSubnetMask(), transportZone.getTunnelType(), false, monitorProtocol,
                                    monitorInterval, idManagerService, dataBroker, futures, transaction)) {
                                LOG.error("Unable to build tunnel {} -- {}", hwVtepDS.getIpAddress(),
                                        tep.getIpAddress());
                            }

                        }
                    }
                }
            }
        }
    }

    private static void tunnelsFromhWVtep(List<HwVtep> cfgdHwVteps, IdManagerService idManagerService,
            List<ListenableFuture<Void>> futures, WriteTransaction transaction, DataBroker dataBroker) {
        for (HwVtep hwTep : cfgdHwVteps) {
            InstanceIdentifier<TransportZone> tzonePath = InstanceIdentifier.builder(TransportZones.class)
                    .child(TransportZone.class, new TransportZoneKey(hwTep.getTransportZone())).build();
            Optional<TransportZone> transportZoneOptional = ItmUtils.read(LogicalDatastoreType.CONFIGURATION,
                    tzonePath, dataBroker);
            Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
            Boolean monitorEnabled = ItmUtils.readMonitoringStateFromCache(dataBroker);
            Class<? extends TunnelMonitoringTypeBase> monitorProtocol = ITMConstants.DEFAULT_MONITOR_PROTOCOL;
            if (transportZoneOptional.isPresent()) {
                TransportZone tzone = transportZoneOptional.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
                                }
                                LOG.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, false, monitorProtocol,
                                        monitorInterval, idManagerService, dataBroker, futures, transaction)) {
                                    LOG.error("Unable to build tunnel {} -- {}", hwTep.getHwIp(),
                                            hwVtepDS.getIpAddress());
                                }
                                //TOR2-TOR1
                                LOG.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, false, monitorProtocol, monitorInterval,
                                        idManagerService, dataBroker, futures, transaction)) {
                                    LOG.error("Unable to build tunnel {} -- {}", hwVtepDS.getIpAddress(),
                                            hwTep.getHwIp());
                                }
                            }
                        }
                        if (sub.getVteps() != null && !sub.getVteps().isEmpty()) {
                            for (Vteps vtep : sub.getVteps()) {
                                if (vtep.getIpAddress().equals(hwTep.getHwIp())) {
                                    continue;
                                }
                                //TOR-OVS
                                String cssID = vtep.getDpnId().toString();
                                LOG.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, false, monitorProtocol, monitorInterval,
                                        idManagerService, dataBroker, futures, transaction)) {
                                    LOG.error("Unable to build tunnel {} -- {}", hwTep.getHwIp(),
                                            vtep.getIpAddress());
                                }
                                //OVS-TOR
                                LOG.trace("wire up {} and {}", vtep, hwTep);
                                boolean useOfTunnel = ItmUtils.falseIfNull(vtep.isOptionOfTunnel());
                                if (!wireUp(vtep.getDpnId(), vtep.getPortname(), sub.getVlanId(),
                                        vtep.getIpAddress(), useOfTunnel, hwTep.getNode_id(), hwTep.getHwIp(),
                                        sub.getPrefix(), sub.getGatewayIp(), hwTep.getIpPrefix(), tunType, false,
                                        monitorProtocol, monitorInterval, idManagerService, dataBroker, futures,
                                        transaction)) {
                                    //do nothing
                                }
                            }

                        }
                    }
                }
            }
        }
    }

    //for tunnels from TOR device
    private static boolean wireUp(String topoId, String srcNodeid, IpAddress srcIp, String dstNodeId,
            IpAddress dstIp, IpPrefix srcSubnet, IpAddress gwIp, IpPrefix dstSubnet,
            Class<? extends TunnelTypeBase> tunType, Boolean monitorEnabled,
            Class<? extends TunnelMonitoringTypeBase> monitorProtocol, Integer monitorInterval,
            IdManagerService idManagerService, DataBroker dataBroker, List<ListenableFuture<Void>> futures,
            WriteTransaction transaction) {
        IpAddress gatewayIpObj = new IpAddress("0.0.0.0".toCharArray());
        IpAddress gwyIpAddress = srcSubnet.equals(dstSubnet) ? gatewayIpObj : gwIp;
        String parentIf = ItmUtils.getHwParentIf(topoId, srcNodeid);
        String tunTypeStr = tunType.getName();
        String tunnelIfName = ItmUtils.getTrunkInterfaceName(idManagerService, parentIf,
                new String(srcIp.getValue()), new String(dstIp.getValue()), tunTypeStr);
        LOG.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, topoId, srcNodeid, tunType,
                srcIp, dstIp, gwyIpAddress, monitorEnabled, monitorProtocol, monitorInterval);
        InstanceIdentifier<Interface> ifIID = InstanceIdentifier.builder(Interfaces.class)
                .child(Interface.class, new InterfaceKey(tunnelIfName)).build();
        LOG.trace(" Writing Trunk Interface to Config DS {}, {} ", ifIID, hwTunnelIf);
        ItmUtils.itmCache.addInterface(hwTunnelIf);
        transaction.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);
        transaction.merge(LogicalDatastoreType.CONFIGURATION, path, tnl, true);
        ItmUtils.itmCache.addExternalTunnel(tnl);
        return true;
    }

    //for tunnels from OVS
    private static boolean wireUp(BigInteger dpnId, String portname, Integer vlanId, IpAddress srcIp,
            Boolean remoteIpFlow, String dstNodeId, IpAddress dstIp, IpPrefix srcSubnet, IpAddress gwIp,
            IpPrefix dstSubnet, Class<? extends TunnelTypeBase> tunType, Boolean monitorEnabled,
            Class<? extends TunnelMonitoringTypeBase> monitorProtocol, Integer monitorInterval,
            IdManagerService idManagerService, DataBroker dataBroker, List<ListenableFuture<Void>> futures,
            WriteTransaction transaction) {
        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,
                new String(srcIp.getValue()), new String(dstIp.getValue()), tunTypeStr);
        LOG.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, monitorProtocol, monitorInterval, remoteIpFlow);
        InstanceIdentifier<Interface> ifIID = InstanceIdentifier.builder(Interfaces.class)
                .child(Interface.class, new InterfaceKey(tunnelIfName)).build();
        LOG.trace(" Writing Trunk Interface to Config DS {}, {} ", ifIID, extTunnelIf);
        transaction.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);
        transaction.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;
    }

}