From 8c03968bb4515d466751644bc6d4fd81386fd296 Mon Sep 17 00:00:00 2001 From: ismaeel Date: Mon, 22 Apr 2024 06:43:16 +0000 Subject: [PATCH] transponders auto discovery --- deploy/component.sh | 25 +- deploy/crdb.sh | 18 +- deploy/mock_blockchain.sh | 17 +- deploy/qdb.sh | 13 +- deploy/tfs.sh | 17 +- manifests/bgpls_speakerservice.yaml | 72 + manifests/cachingservice.yaml | 50 +- manifests/contextservice.yaml | 94 +- manifests/dbscanservingservice.yaml | 68 +- manifests/deviceservice.yaml | 70 +- manifests/dltservice.yaml | 118 +- manifests/e2e_orchestratorservice.yaml | 68 +- manifests/forecasterservice.yaml | 86 +- manifests/interdomainservice.yaml | 64 +- manifests/l3_attackmitigatorservice.yaml | 86 +- .../l3_centralizedattackdetectorservice.yaml | 102 +- .../l3_distributedattackdetectorservice.yaml | 48 +- manifests/load_generatorservice.yaml | 60 +- manifests/mock_blockchain.yaml | 50 +- manifests/monitoringservice.yaml | 66 +- manifests/nbiservice.yaml | 70 +- manifests/nginx_ingress_http.yaml | 74 +- manifests/opticalattackdetectorservice.yaml | 78 +- manifests/opticalattackmanagerservice.yaml | 66 +- manifests/opticalattackmitigatorservice.yaml | 68 +- manifests/opticalcontrollerservice.yaml | 72 + manifests/pathcompservice.yaml | 132 +- manifests/policyservice.yaml | 38 +- manifests/prometheus.yaml | 31 +- manifests/servicemonitors.yaml | 256 +- manifests/serviceservice.yaml | 72 +- manifests/sliceservice.yaml | 82 +- manifests/teservice.yaml | 78 +- manifests/webuiservice.yaml | 146 +- manifests/ztpservice.yaml | 38 +- my_deploy.sh | 8 +- ofc24 | 1 + proto/bgpls.proto | 70 + proto/context.proto | 69 + proto/openconfig_device.proto | 23 + scripts/expose_ingress_grpc.sh | 55 + scripts/run_tests_docker.sh | 88 + ...n_tests_locally-optical-attack-detector.sh | 102 + scripts/show_logs_bgp.sh | 27 + scripts/show_logs_opticalcontroller.sh | 27 + scripts/start_webui_dev_mode.sh | 37 + scripts/wait_context_nats.sh | 28 + src/bgpls_speaker/.gitlab-ci.yml | 105 + src/bgpls_speaker/Config.py | 13 + src/bgpls_speaker/Dockerfile | 110 + src/bgpls_speaker/__init__.py | 13 + src/bgpls_speaker/client/BgplsClient.py | 91 + src/bgpls_speaker/client/__init__.py | 13 + src/bgpls_speaker/quick_deploy.sh | 438 + src/bgpls_speaker/requirements.in | 23 + src/bgpls_speaker/service/BgplsService.py | 31 + .../service/BgplsServiceServicerImpl.py | 178 + src/bgpls_speaker/service/__init__.py | 13 + src/bgpls_speaker/service/__main__.py | 63 + .../service/java/BGP4Parameters_3.xml | 65 + .../service/java/exec_speakear_java.sh | 19 + .../.settings/org.eclipse.jdt.core.prefs | 8 + .../netphony-topology/BGP4Parameters_3.xml | 65 + .../service/java/netphony-topology/CHANGELOG | 50 + .../service/java/netphony-topology/LICENSE | 202 + .../service/java/netphony-topology/VERSION | 1 + .../java/netphony-topology/doc/Examples.md | 133 + .../java/netphony-topology/doc/TAPIExample.md | 27 + .../doc/TopologyFileDescription.md | 127 + .../doc/figures/1wayTest.png | Bin 0 -> 53545 bytes .../doc/figures/2wayTest.png | Bin 0 -> 54450 bytes .../service/java/netphony-topology/log4j2.xml | 36 + .../service/java/netphony-topology/pom.xml | 497 + .../bgp4session/BGP4PeerInitiatedSession.java | 188 + .../tid/bgp4Peer/bgp4session/BGP4Session.java | 44 + .../bgp4session/BGP4SessionClient.java | 222 + .../BGP4SessionExistsException.java | 24 + .../bgp4session/BGP4SessionsInformation.java | 146 + .../bgp4session/BGP4StateSession.java | 28 + .../bgp4session/ConnectRetryTimer.java | 30 + .../bgp4Peer/bgp4session/DeadTimerThread.java | 72 + .../bgp4session/GenericBGP4Session.java | 908 + .../bgp4Peer/bgp4session/KeepAliveThread.java | 98 + .../bgp4session/KeepWaitTimerTask.java | 58 + .../bgp4session/OpenWaitTimerTask.java | 59 + .../teraflow/tid/bgp4Peer/grpc/grpcApp.java | 38 + .../tid/bgp4Peer/grpc/grpcClient.java | 368 + .../tid/bgp4Peer/grpc/updateServiceImpl.java | 42 + .../tid/bgp4Peer/json/bgpMarshal.java | 82 + .../management/BGP4ManagementServer.java | 85 + .../management/BGP4ManagementSession.java | 199 + .../tid/bgp4Peer/models/LinkNLRIMsg.java | 298 + .../tid/bgp4Peer/models/NodeNLRIMsg.java | 197 + .../tid/bgp4Peer/models/PathAttributeMsg.java | 89 + .../tid/bgp4Peer/models/UpdateMsg.java | 99 + .../tid/bgp4Peer/models/UpdateMsgList.java | 151 + .../tid/bgp4Peer/peer/BGP4Exception.java | 20 + .../tid/bgp4Peer/peer/BGP4LSPeerInfo.java | 85 + .../tid/bgp4Peer/peer/BGP4Parameters.java | 540 + .../peer/BGP4SessionClientManager.java | 160 + .../peer/BGP4SessionServerManager.java | 160 + .../teraflow/tid/bgp4Peer/peer/BGPPeer.java | 407 + .../tid/bgp4Peer/peer/BGPPeerMain.java | 37 + .../tid/bgp4Peer/peer/SaveTopologyinDB.java | 300 + .../tid/bgp4Peer/peer/SendTopology.java | 1028 + .../tid/bgp4Peer/tedb/BGP4DomainTEDB.java | 51 + .../bgp4Peer/tedb/BGP4IntradomainTEDB.java | 67 + .../tid/bgp4Peer/tedb/IntraTEDBS.java | 29 + .../bgp4Peer/updateTEDB/UpdateDispatcher.java | 56 + .../tid/bgp4Peer/updateTEDB/UpdateLink.java | 94 + .../updateTEDB/UpdateProccesorThread.java | 505 + .../updateTEDB/UpdaterThreadRedisTED.java | 77 + .../tedb/DatabaseControlSimplifiedLSA.java | 174 + .../java/eu/teraflow/tid/tedb/DomainTEDB.java | 85 + .../java/eu/teraflow/tid/tedb/EdgeUtils.java | 34 + .../eu/teraflow/tid/tedb/FileTEDBUpdater.java | 3585 + .../eu/teraflow/tid/tedb/IT_Resources.java | 147 + .../eu/teraflow/tid/tedb/InterDomainEdge.java | 221 + .../eu/teraflow/tid/tedb/IntraDomainEdge.java | 298 + .../tid/tedb/IntraDomainWeightEdge.java | 131 + .../main/java/eu/teraflow/tid/tedb/Layer.java | 37 + .../java/eu/teraflow/tid/tedb/MDTEDB.java | 270 + .../eu/teraflow/tid/tedb/MultiDomainTEDB.java | 25 + .../eu/teraflow/tid/tedb/MultiLayerTEDB.java | 473 + .../java/eu/teraflow/tid/tedb/Node_Info.java | 207 + .../teraflow/tid/tedb/ReachabilityEntry.java | 85 + .../tid/tedb/ReachabilityManager.java | 162 + .../eu/teraflow/tid/tedb/SSONInformation.java | 88 + .../eu/teraflow/tid/tedb/SSONListener.java | 28 + .../java/eu/teraflow/tid/tedb/SimpleTEDB.java | 786 + .../main/java/eu/teraflow/tid/tedb/TEDB.java | 37 + .../eu/teraflow/tid/tedb/TEDBUpdater.java | 19 + .../eu/teraflow/tid/tedb/TEDListener.java | 41 + .../eu/teraflow/tid/tedb/TE_Information.java | 679 + .../eu/teraflow/tid/tedb/WSONInformation.java | 74 + .../eu/teraflow/tid/tedb/WSONListener.java | 19 + .../controllers/TEDUpdaterController.java | 272 + .../controllers/TEDUpdaterFloodlight.java | 367 + .../tid/tedb/controllers/TEDUpdaterNOX.java | 419 + .../tid/tedb/controllers/TEDUpdaterODL.java | 351 + .../tid/tedb/controllers/TEDUpdaterRYU.java | 355 + .../tid/tedb/controllers/TEDUpdaterTREMA.java | 449 + .../teraflow/tid/tedb/elements/AuthInfo.java | 52 + .../teraflow/tid/tedb/elements/Bandwidth.java | 63 + .../teraflow/tid/tedb/elements/BgpParams.java | 19 + .../teraflow/tid/tedb/elements/EndPoint.java | 81 + .../tid/tedb/elements/IPNodeParams.java | 23 + .../eu/teraflow/tid/tedb/elements/Intf.java | 211 + .../tid/tedb/elements/IsisParams.java | 19 + .../eu/teraflow/tid/tedb/elements/Link.java | 190 + .../teraflow/tid/tedb/elements/Location.java | 57 + .../eu/teraflow/tid/tedb/elements/Node.java | 211 + .../tid/tedb/elements/OspfParams.java | 19 + .../eu/teraflow/tid/tedb/elements/Path.java | 67 + .../tid/tedb/elements/PhyLinkParams.java | 55 + .../tid/tedb/elements/RouterDesc.java | 133 + .../tid/tedb/elements/RouterInfoPM.java | 243 + .../teraflow/tid/tedb/elements/Service.java | 177 + .../tedb/elements/StaticRoutingParams.java | 19 + .../src/main/proto/grpcService.proto | 80 + .../TM_COP_example1/TMConfCOP.xml | 27 + .../TM_COP_example1/network1.xml | 220 + .../TM_TAPI_example1/TMConfTAPI.xml | 27 + .../TM_TAPI_example1/network1.xml | 171 + .../bgpls_example1/BGP4Parameters_1.xml | 67 + .../bgpls_example1/BGP4Parameters_2.xml | 66 + .../bgpls_example1/network1.xml | 220 + .../conf1wayTest/BGPLS1.xml | 74 + .../conf1wayTest/BGPLS2.xml | 80 + .../conf1wayTest/BGPLS3.xml | 80 + .../sample-config-files/conf1wayTest/TM1.xml | 41 + .../sample-config-files/conf1wayTest/TM2.xml | 41 + .../sample-config-files/conf1wayTest/TM3.xml | 41 + ...MConfiguration_BGPLSreader_UNIFYwriter.xml | 40 + .../conf1wayTest/network1.xml | 233 + .../conf1wayTest/network2.xml | 274 + .../conf1wayTest/network3.xml | 239 + .../conf2waysReal/BGPLS1_2way.xml | 68 + .../conf2waysReal/BGPLS2_2way.xml | 74 + .../conf2waysReal/BGPLS3_2way.xml | 68 + .../sample-config-files/conf2waysReal/README | 37 + .../sample-config-files/conf2waysReal/TM1.xml | 41 + .../sample-config-files/conf2waysReal/TM2.xml | 41 + .../sample-config-files/conf2waysReal/TM3.xml | 41 + .../conf2waysReal/network1.xml | 239 + .../conf2waysReal/network2.xml | 274 + .../conf2waysReal/network3.xml | 239 + .../examples/BGP4Parameters.xml | 69 + .../examples/BGP4ParametersRX.xml | 68 + .../examples/BGP4ParametersTX.xml | 68 + .../examples/BGP4ParametersTXRX.xml | 74 + .../examples/BGP4Parameters_1.xml | 67 + .../examples/BGP4Parameters_1_IT.xml | 67 + .../examples/BGP4Parameters_2.xml | 66 + .../examples/BGP4Parameters_PCE.xml | 67 + .../examples/BGP4Parameters_TM.xml | 67 + .../examples/EmulatedTopology.xml | 604 + .../examples/EmulatedTopologyECOC.xml | 340 + .../examples/TMConfiguration.xml | 40 + .../examples/TMConfiguration2.xml | 34 + .../examples/TMConfigurationCOP.xml | 36 + .../TMConfiguration_BGPLSreader_COPwriter.xml | 40 + ...TMConfiguration_BGPLSreader_IETFwriter.xml | 40 + ...MConfiguration_BGPLSreader_UNIFYwriter.xml | 40 + .../TMConfiguration_COPreader_BGPLSsender.xml | 42 + .../examples/TMConfiguration_COPsender.xml | 40 + .../sample-config-files/examples/log4j2.xml | 30 + .../examples/network1_pce.xml | 172 + .../sample-config-files/examples/total.xml | 213 + .../sample-config-files/examples/total101.xml | 144 + .../examples/total10v2.xml | 261 + .../tid/bgp/bgp4Peer/tests/BGP4PeerTest.java | 130 + .../src/test/resources/BGP4Parameters_1.xml | 67 + .../test/resources/BGP4Parameters_1_IT.xml | 67 + .../src/test/resources/BGP4Parameters_2.xml | 66 + .../src/test/resources/EmulatedTopology.xml | 604 + .../test/resources/EmulatedTopologyECOC.xml | 340 + .../src/test/resources/log4j2.xml | 27 + .../src/test/resources/network1.xml | 227 + .../src/main/proto/updateServiceGrpc.java | 320 + .../java/netphony-topology/topology.iml | 87 + .../service/tools/DiscoveredDBManager.py | 318 + src/bgpls_speaker/service/tools/GrpcServer.py | 170 + src/bgpls_speaker/service/tools/JavaRunner.py | 107 + src/bgpls_speaker/service/tools/Tools.py | 202 + src/bgpls_speaker/service/tools/__init__.py | 13 + .../service/tools/json_loader.py | 42 + .../service/tools/protos/grpcService.proto | 81 + .../service/tools/protos/grpcService_pb2.py | 77 + .../tools/protos/grpcService_pb2_grpc.py | 70 + src/bgpls_speaker/tests/.gitignore | 1 + src/bgpls_speaker/tests/__init__.py | 13 + src/bgpls_speaker/tests/test_unitary.py | 18 + src/common/Constants.py | 4 + .../tools/context_queries/OpticalConfig.py | 58 + src/common/tools/descriptor/Tools.py | 4 +- src/common/tools/mutex_queues/MutexQueues.py | 11 +- src/context/.gitlab-ci.yml | 2 +- src/context/client/ContextClient.py | 33 +- .../service/ContextServiceServicerImpl.py | 30 +- src/context/service/database/Device.py | 19 +- src/context/service/database/Events.py | 11 +- src/context/service/database/Link.py | 6 +- src/context/service/database/OpticalConfig.py | 144 + src/context/service/database/Service.py | 7 +- .../database/models/OpticalConfigModel.py | 70 + .../database/models/OpticalLinkModel.py | 78 + .../database/models/enums/DeviceDriver.py | 1 + .../database/models/enums/ServiceType.py | 1 + .../database/models/enums/_GrpcToEnum.py | 12 +- .../service/database/uuids/OpticalConfig.py | 17 + src/dbscanserving/.gitlab-ci.yml | 2 +- src/device/.gitlab-ci.yml | 2 +- src/device/Config.py | 6 + src/device/Dockerfile | 6 +- src/device/client/DeviceClient.py | 11 +- src/device/service/DeviceService.py | 8 + .../service/DeviceServiceServicerImpl.py | 16 +- src/device/service/OpenConfigServicer.py | 105 + src/device/service/Tools.py | 93 +- .../service/driver_api/DriverInstanceCache.py | 7 +- src/device/service/drivers/__init__.py | 19 +- .../service/drivers/oc_driver/OCDriver.py | 327 + .../drivers/oc_driver/RetryDecorator.py | 46 + src/device/service/drivers/oc_driver/Tools.py | 38 + .../service/drivers/oc_driver/__init__.py | 14 + .../templates/Interfaces/__init__.py | 14 + .../templates/Interfaces/interfaces.py | 43 + .../drivers/oc_driver/templates/Tools.py | 300 + .../oc_driver/templates/VPN/__init__.py | 14 + .../oc_driver/templates/VPN/physical.py | 210 + .../drivers/oc_driver/templates/__init__.py | 14 + .../openconfig/templates/Interfaces.py | 11 +- .../drivers/openconfig/templates/Inventory.py | 7 +- .../openconfig/templates/RoutingPolicy.py | 2 +- src/device/tests/test_unitary_ietf_actn.py | 12 + src/dlt/.gitlab-ci.yml | 4 +- src/e2e_orchestrator/.gitlab-ci.yml | 2 +- src/forecaster/.gitlab-ci.yml | 2 +- src/interdomain/.gitlab-ci.yml | 2 +- src/l3_attackmitigator/.gitlab-ci.yml | 2 +- .../.gitlab-ci.yml | 2 +- .../.gitlab-ci.yml | 2 +- src/load_generator/.gitlab-ci.yml | 2 +- src/monitoring/.gitlab-ci.yml | 2 +- src/monitoring/tests/test_unitary.py | 4 +- src/nbi/.gitlab-ci.yml | 2 +- .../nbi_plugins/ietf_l3vpn/L3VPN_Services.py | 37 +- src/opticalattackdetector/.gitlab-ci.yml | 120 +- ...pticalAttackDetectorServiceServicerImpl.py | 2 +- .../tests/test_unitary.py | 29 +- src/opticalattackmanager/.gitlab-ci.yml | 80 +- src/opticalattackmitigator/.gitlab-ci.yml | 72 +- src/opticalcontroller/.gitlab-ci.yml | 105 + src/opticalcontroller/Dockerfile | 71 + src/opticalcontroller/OpticalController.py | 245 + src/opticalcontroller/README.md | 17 + src/opticalcontroller/RSA.py | 931 + src/opticalcontroller/__init__.py | 13 + src/opticalcontroller/dijsktra.py | 240 + src/opticalcontroller/images/topo.png | Bin 0 -> 30289 bytes src/opticalcontroller/json_files/nodes.json | 39 + .../json_files/optical_TFSworking.json | 486 + .../json_files/optical_topoTFS.json | 1836 + src/opticalcontroller/json_files/tfs.json | 686 + .../json_files/topo_2_links.json | 1530 + .../json_files/topology-optical.json | 252 + .../json_files/topology-optical2.json | 324 + src/opticalcontroller/requirements.in | 21 + src/opticalcontroller/tools.py | 189 + src/opticalcontroller/variables.py | 32 + src/pathcomp/.gitlab-ci.yml | 6 +- src/pathcomp/frontend/Dockerfile | 9 +- src/policy/.gitlab-ci.yml | 6 +- .../.mvn/wrapper/maven-wrapper.properties | 2 +- src/policy/pom.xml | 14 +- .../java/org/etsi/tfs/policy/Serializer.java | 18 +- .../etsi/tfs/policy/SimpleLivenessCheck.java | 2 +- .../etsi/tfs/policy/SimpleReadinessCheck.java | 2 +- .../policy/common/ApplicationProperties.java | 59 + .../tfs/policy/context/ContextGateway.java | 2 +- .../policy/context/ContextGatewayImpl.java | 6 +- .../tfs/policy/context/ContextService.java | 2 +- .../policy/context/ContextServiceImpl.java | 6 +- .../tfs/policy/device/DeviceGatewayImpl.java | 4 +- .../tfs/policy/device/DeviceServiceImpl.java | 4 +- .../ExternalServiceFailureException.java | 28 + .../exception/GeneralExceptionHandler.java | 58 + .../monitoring/MonitoringGatewayImpl.java | 4 +- .../monitoring/MonitoringServiceImpl.java | 4 +- .../etsi/tfs/policy/policy/PolicyGateway.java | 21 + .../tfs/policy/policy/PolicyGatewayImpl.java | 130 + .../etsi/tfs/policy/policy/PolicyService.java | 35 + .../tfs/policy/policy/PolicyServiceImpl.java | 983 + .../policy/policy/model/BooleanOperator.java | 23 + .../policy/model/NumericalOperator.java | 27 + .../tfs/policy/policy/model/PolicyRule.java | 36 + .../policy/policy/model/PolicyRuleAction.java | 55 + .../policy/model/PolicyRuleActionConfig.java | 43 + .../policy/model/PolicyRuleActionEnum.java | 27 + .../policy/policy/model/PolicyRuleBase.java | 29 + .../policy/policy/model/PolicyRuleBasic.java | 119 + .../policy/model/PolicyRuleCondition.java | 83 + .../policy/policy/model/PolicyRuleDevice.java | 51 + .../policy/model/PolicyRuleService.java | 65 + .../policy/policy/model/PolicyRuleState.java | 50 + .../policy/model/PolicyRuleStateEnum.java | 31 + .../policy/policy/model/PolicyRuleType.java | 24 + .../policy/model/PolicyRuleTypeDevice.java | 41 + .../policy/model/PolicyRuleTypeService.java | 41 + .../PolicyRuleConditionFieldsGetter.java | 47 + .../service/PolicyRuleConditionValidator.java | 139 + .../policy/service/ServiceGatewayImpl.java | 4 +- .../policy/service/ServiceServiceImpl.java | 4 +- .../etsi/tfs/policy/PolicyAddDeviceTest.java | 250 + .../etsi/tfs/policy/PolicyAddServiceTest.java | 253 + .../tfs/policy/PolicyDeleteServiceTest.java | 132 + .../tfs/policy/PolicyGrpcServiceTest.java | 383 + .../policy/PolicyRuleBasicValidationTest.java | 18 +- .../PolicyRuleConditionValidationTest.java | 4 +- .../PolicyRuleDeviceValidationTest.java | 20 +- .../PolicyRuleServiceValidationTest.java | 23 +- .../tfs/policy/PolicyUpdateDeviceTest.java | 206 + .../tfs/policy/PolicyUpdateServiceTest.java | 217 + .../org/etsi/tfs/policy/SerializerTest.java | 24 +- .../generated-sources/grpc/acl/Acl.java | 8671 +- .../grpc/context/ContextOuterClass.java | 142055 +++++++-------- .../grpc/context/ContextService.java | 109 +- .../grpc/context/ContextServiceBean.java | 542 +- .../grpc/context/ContextServiceClient.java | 161 +- .../grpc/context/ContextServiceGrpc.java | 5524 +- .../context/MutinyContextServiceGrpc.java | 884 +- .../grpc/context_policy/ContextPolicy.java | 61 +- .../context_policy/ContextPolicyService.java | 21 +- .../ContextPolicyServiceBean.java | 65 +- .../ContextPolicyServiceClient.java | 36 +- .../ContextPolicyServiceGrpc.java | 846 +- .../MutinyContextPolicyServiceGrpc.java | 134 +- .../generated-sources/grpc/device/Device.java | 1801 +- .../grpc/device/DeviceService.java | 21 +- .../grpc/device/DeviceServiceBean.java | 65 +- .../grpc/device/DeviceServiceClient.java | 36 +- .../grpc/device/DeviceServiceGrpc.java | 819 +- .../grpc/device/MutinyDeviceServiceGrpc.java | 136 +- .../grpc/kpi_sample_types/KpiSampleTypes.java | 577 +- .../grpc/monitoring/Monitoring.java | 40628 ++--- .../grpc/monitoring/MonitoringService.java | 47 +- .../monitoring/MonitoringServiceBean.java | 205 +- .../monitoring/MonitoringServiceClient.java | 72 +- .../monitoring/MonitoringServiceGrpc.java | 2164 +- .../MutinyMonitoringServiceGrpc.java | 357 +- .../grpc/policy/MutinyPolicyServiceGrpc.java | 187 +- .../generated-sources/grpc/policy/Policy.java | 19800 +- .../grpc/policy/PolicyAction.java | 3354 +- .../grpc/policy/PolicyCondition.java | 2404 +- .../grpc/policy/PolicyService.java | 27 +- .../grpc/policy/PolicyServiceBean.java | 98 +- .../grpc/policy/PolicyServiceClient.java | 45 +- .../grpc/policy/PolicyServiceGrpc.java | 1137 +- .../service/MutinyServiceServiceGrpc.java | 119 +- .../grpc/service/Service.java | 55 +- .../grpc/service/ServiceService.java | 19 +- .../grpc/service/ServiceServiceBean.java | 54 +- .../grpc/service/ServiceServiceClient.java | 33 +- .../grpc/service/ServiceServiceGrpc.java | 713 +- src/policy/target/kubernetes/kubernetes.yml | 45 +- src/service/.gitlab-ci.yml | 2 +- src/service/Dockerfile | 2 +- src/service/requirements.in | 1 + .../service/ServiceServiceServicerImpl.py | 129 +- src/service/service/__main__.py | 3 +- .../service_handler_api/FilterFields.py | 2 + .../service/service_handlers/__init__.py | 7 + .../service_handlers/oc/ConfigRules.py | 255 + .../service_handlers/oc/OCServiceHandler.py | 169 + .../service/service_handlers/oc/OCTools.py | 142 + .../service/service_handlers/oc/__init__.py | 14 + .../service/task_scheduler/TaskExecutor.py | 33 +- src/service/service/tools/OpticalTools.py | 297 + src/service/service/tools/replies.py | 321 + src/slice/.gitlab-ci.yml | 83 +- src/slice/Dockerfile | 13 +- .../service/slice_grouper/MetricsExporter.py | 4 +- src/slice/tests/test_unitary.py | 48 +- src/tests/.gitlab-ci.yml | 8 +- src/tests/ecoc22/.gitlab-ci.yml | 106 + src/tests/ecoc22/Dockerfile | 101 + src/tests/ecoc22/deploy_specs.sh | 22 +- src/tests/ecoc22/requirements.in | 15 + .../ecoc22/tests/test_functional_bootstrap.py | 28 +- .../ecoc22/tests/test_functional_cleanup.py | 4 +- .../tests/test_functional_create_service.py | 4 +- .../tests/test_functional_delete_service.py | 4 +- src/tests/ofc22/.gitlab-ci.yml | 109 + src/tests/ofc22/Dockerfile | 101 + src/tests/ofc22/deploy_specs.sh | 18 +- src/tests/ofc22/requirements.in | 15 + .../ofc22/tests/test_functional_bootstrap.py | 4 +- .../ofc22/tests/test_functional_cleanup.py | 4 +- .../tests/test_functional_create_service.py | 4 +- .../tests/test_functional_delete_service.py | 4 +- src/tests/ofc24/.gitlab-ci.yml | 106 + src/tests/ofc24/1.context.json | 19 + src/tests/ofc24/2.device1.json | 91 + src/tests/ofc24/3.device2.json | 91 + src/tests/ofc24/4.device3_R1.json | 188 + src/tests/ofc24/5.device4_R2.json | 189 + src/tests/ofc24/6.links.json | 28 + src/tests/ofc24/7.service-bidir.json | 22 + src/tests/ofc24/7.service-unidir.json | 22 + src/tests/ofc24/Dockerfile | 101 + src/tests/ofc24/README.md | 21 + src/tests/ofc24/copy.sh | 26 + src/tests/ofc24/deploy-node-agents.sh | 85 + src/tests/ofc24/deploy_specs.sh | 163 + src/tests/ofc24/descriptors_topology.json | 150 + src/tests/ofc24/requirements.in | 15 + src/tests/ofc24/run_test.sh | 17 + src/tests/ofc24/startExtraNetConfigAgent.sh | 48 + src/tests/ofc24/start_topo.sh | 70 + src/tests/ofc24/tests/__init__.py | 14 + .../ofc24/tests/test_functional_bootstrap.py | 67 + .../ofc24/tests/test_functional_cleanup.py | 44 + .../tests/test_functional_create_service.py | 102 + .../tests/test_functional_delete_service.py | 74 + .../tools/mock_ietf_actn_sdn_ctrl/README.md | 42 +- .../tools/mock_ietf_actn_sdn_ctrl/build.sh | 3 + .../tools/mock_ietf_actn_sdn_ctrl/run.sh | 3 + src/webui/.gitlab-ci.yml | 54 +- src/webui/Dockerfile | 2 + src/webui/requirements.in | 8 +- src/webui/service/__init__.py | 6 + src/webui/service/bgpls/__init__.py | 13 + src/webui/service/bgpls/forms.py | 86 + src/webui/service/bgpls/routes.py | 244 + src/webui/service/device/routes.py | 2 +- src/webui/service/main/routes.py | 2 + src/webui/service/opticalconfig/__init__.py | 14 + src/webui/service/opticalconfig/forms.py | 22 + src/webui/service/opticalconfig/routes.py | 301 + .../topology_icons/Acknowledgements.txt | 1 + .../static/topology_icons/p4-switch.png | Bin 0 -> 6288 bytes src/webui/service/templates/base.html | 14 + src/webui/service/templates/bgpls/add.html | 162 + .../service/templates/bgpls/addSpeaker.html | 88 + .../service/templates/bgpls/editSpeakers.html | 70 + src/webui/service/templates/bgpls/home.html | 110 + .../opticalconfig/add_transceiver.html | 55 + .../templates/opticalconfig/details.html | 123 + .../service/templates/opticalconfig/home.html | 84 + .../opticalconfig/update_interface.html | 89 + src/webui/service/templates/topology/add.html | 162 + .../templates/topology/addSpeaker.html | 88 + .../templates/topology/editSpeakers.html | 70 + .../service/templates/topology/home.html | 112 + src/webui/service/topology/__init__.py | 14 + src/webui/service/topology/forms.py | 86 + src/webui/service/topology/routes.py | 245 + src/ztp/.gitlab-ci.yml | 6 +- src/ztp/.mvn/wrapper/maven-wrapper.properties | 2 +- src/ztp/pom.xml | 5 +- .../org/etsi/tfs/ztp/ContextSubscriber.java | 6 +- .../java/org/etsi/tfs/ztp/Serializer.java | 2 +- .../org/etsi/tfs/ztp/SimpleLivenessCheck.java | 2 +- .../etsi/tfs/ztp/SimpleReadinessCheck.java | 2 +- .../java/org/etsi/tfs/ztp/ZtpGatewayImpl.java | 2 +- .../java/org/etsi/tfs/ztp/ZtpServiceImpl.java | 4 +- .../tfs/ztp/context/ContextGatewayImpl.java | 4 +- .../tfs/ztp/context/ContextServiceImpl.java | 4 +- .../tfs/ztp/device/DeviceGatewayImpl.java | 4 +- .../tfs/ztp/device/DeviceServiceImpl.java | 4 +- .../etsi/tfs/ztp/ContextSubscriberTest.java | 2 +- .../etsi/tfs/ztp/MockZtpConfiguration.java | 6 +- .../java/org/etsi/tfs/ztp/SerializerTest.java | 2 +- .../tfs/ztp/ZtpFunctionalServiceTest.java | 2 +- .../java/org/etsi/tfs/ztp/ZtpServiceTest.java | 2 +- .../generated-sources/grpc/acl/Acl.java | 8671 +- .../grpc/context/ContextOuterClass.java | 142055 +++++++-------- .../grpc/context/ContextService.java | 109 +- .../grpc/context/ContextServiceBean.java | 542 +- .../grpc/context/ContextServiceClient.java | 161 +- .../grpc/context/ContextServiceGrpc.java | 5524 +- .../context/MutinyContextServiceGrpc.java | 884 +- .../generated-sources/grpc/device/Device.java | 1801 +- .../grpc/device/DeviceService.java | 21 +- .../grpc/device/DeviceServiceBean.java | 65 +- .../grpc/device/DeviceServiceClient.java | 36 +- .../grpc/device/DeviceServiceGrpc.java | 819 +- .../grpc/device/MutinyDeviceServiceGrpc.java | 136 +- .../grpc/kpi_sample_types/KpiSampleTypes.java | 577 +- .../grpc/monitoring/Monitoring.java | 40628 ++--- .../grpc/monitoring/MonitoringService.java | 47 +- .../monitoring/MonitoringServiceBean.java | 205 +- .../monitoring/MonitoringServiceClient.java | 72 +- .../monitoring/MonitoringServiceGrpc.java | 2164 +- .../MutinyMonitoringServiceGrpc.java | 357 +- .../grpc/ztp/MutinyZtpServiceGrpc.java | 153 +- .../generated-sources/grpc/ztp/Ztp.java | 8928 +- .../grpc/ztp/ZtpService.java | 23 +- .../grpc/ztp/ZtpServiceBean.java | 76 +- .../grpc/ztp/ZtpServiceClient.java | 39 +- .../grpc/ztp/ZtpServiceGrpc.java | 925 +- src/ztp/target/kubernetes/kubernetes.yml | 49 +- test.py | 41 + 544 files changed, 262221 insertions(+), 239297 deletions(-) create mode 100644 manifests/bgpls_speakerservice.yaml create mode 100644 manifests/opticalcontrollerservice.yaml create mode 100644 ofc24 create mode 100644 proto/bgpls.proto create mode 100644 proto/openconfig_device.proto create mode 100644 scripts/expose_ingress_grpc.sh create mode 100644 scripts/run_tests_docker.sh create mode 100644 scripts/run_tests_locally-optical-attack-detector.sh create mode 100644 scripts/show_logs_bgp.sh create mode 100644 scripts/show_logs_opticalcontroller.sh create mode 100644 scripts/start_webui_dev_mode.sh create mode 100644 scripts/wait_context_nats.sh create mode 100644 src/bgpls_speaker/.gitlab-ci.yml create mode 100644 src/bgpls_speaker/Config.py create mode 100644 src/bgpls_speaker/Dockerfile create mode 100644 src/bgpls_speaker/__init__.py create mode 100644 src/bgpls_speaker/client/BgplsClient.py create mode 100644 src/bgpls_speaker/client/__init__.py create mode 100644 src/bgpls_speaker/quick_deploy.sh create mode 100644 src/bgpls_speaker/requirements.in create mode 100644 src/bgpls_speaker/service/BgplsService.py create mode 100644 src/bgpls_speaker/service/BgplsServiceServicerImpl.py create mode 100644 src/bgpls_speaker/service/__init__.py create mode 100644 src/bgpls_speaker/service/__main__.py create mode 100644 src/bgpls_speaker/service/java/BGP4Parameters_3.xml create mode 100644 src/bgpls_speaker/service/java/exec_speakear_java.sh create mode 100644 src/bgpls_speaker/service/java/netphony-topology/.settings/org.eclipse.jdt.core.prefs create mode 100644 src/bgpls_speaker/service/java/netphony-topology/BGP4Parameters_3.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/CHANGELOG create mode 100644 src/bgpls_speaker/service/java/netphony-topology/LICENSE create mode 100644 src/bgpls_speaker/service/java/netphony-topology/VERSION create mode 100644 src/bgpls_speaker/service/java/netphony-topology/doc/Examples.md create mode 100644 src/bgpls_speaker/service/java/netphony-topology/doc/TAPIExample.md create mode 100644 src/bgpls_speaker/service/java/netphony-topology/doc/TopologyFileDescription.md create mode 100644 src/bgpls_speaker/service/java/netphony-topology/doc/figures/1wayTest.png create mode 100644 src/bgpls_speaker/service/java/netphony-topology/doc/figures/2wayTest.png create mode 100644 src/bgpls_speaker/service/java/netphony-topology/log4j2.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/pom.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4PeerInitiatedSession.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4Session.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionClient.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionExistsException.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionsInformation.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4StateSession.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/ConnectRetryTimer.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/DeadTimerThread.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/GenericBGP4Session.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/KeepAliveThread.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/KeepWaitTimerTask.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/OpenWaitTimerTask.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/grpcApp.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/grpcClient.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/updateServiceImpl.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/json/bgpMarshal.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/management/BGP4ManagementServer.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/management/BGP4ManagementSession.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/LinkNLRIMsg.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/NodeNLRIMsg.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/PathAttributeMsg.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/UpdateMsg.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/UpdateMsgList.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4Exception.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4LSPeerInfo.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4Parameters.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4SessionClientManager.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4SessionServerManager.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGPPeer.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGPPeerMain.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/SaveTopologyinDB.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/SendTopology.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/BGP4DomainTEDB.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/BGP4IntradomainTEDB.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/IntraTEDBS.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateDispatcher.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateLink.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateProccesorThread.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdaterThreadRedisTED.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/DatabaseControlSimplifiedLSA.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/DomainTEDB.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/EdgeUtils.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/FileTEDBUpdater.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/IT_Resources.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/InterDomainEdge.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/IntraDomainEdge.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/IntraDomainWeightEdge.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/Layer.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MDTEDB.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MultiDomainTEDB.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MultiLayerTEDB.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/Node_Info.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/ReachabilityEntry.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/ReachabilityManager.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SSONInformation.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SSONListener.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SimpleTEDB.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDB.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDBUpdater.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDListener.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TE_Information.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/WSONInformation.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/WSONListener.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterController.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterFloodlight.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterNOX.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterODL.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterRYU.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterTREMA.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/AuthInfo.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Bandwidth.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/BgpParams.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/EndPoint.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/IPNodeParams.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Intf.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/IsisParams.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Link.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Location.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Node.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/OspfParams.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Path.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/PhyLinkParams.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/RouterDesc.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/RouterInfoPM.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Service.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/StaticRoutingParams.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/proto/grpcService.proto create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/TM_COP_example1/TMConfCOP.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/TM_COP_example1/network1.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/TM_TAPI_example1/TMConfTAPI.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/TM_TAPI_example1/network1.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/bgpls_example1/BGP4Parameters_1.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/bgpls_example1/BGP4Parameters_2.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/bgpls_example1/network1.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/conf1wayTest/BGPLS1.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/conf1wayTest/BGPLS2.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/conf1wayTest/BGPLS3.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/conf1wayTest/TM1.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/conf1wayTest/TM2.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/conf1wayTest/TM3.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/conf1wayTest/TMConfiguration_BGPLSreader_UNIFYwriter.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/conf1wayTest/network1.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/conf1wayTest/network2.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/conf1wayTest/network3.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/conf2waysReal/BGPLS1_2way.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/conf2waysReal/BGPLS2_2way.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/conf2waysReal/BGPLS3_2way.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/conf2waysReal/README create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/conf2waysReal/TM1.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/conf2waysReal/TM2.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/conf2waysReal/TM3.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/conf2waysReal/network1.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/conf2waysReal/network2.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/conf2waysReal/network3.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/BGP4Parameters.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/BGP4ParametersRX.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/BGP4ParametersTX.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/BGP4ParametersTXRX.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/BGP4Parameters_1.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/BGP4Parameters_1_IT.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/BGP4Parameters_2.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/BGP4Parameters_PCE.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/BGP4Parameters_TM.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/EmulatedTopology.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/EmulatedTopologyECOC.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/TMConfiguration.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/TMConfiguration2.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/TMConfigurationCOP.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/TMConfiguration_BGPLSreader_COPwriter.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/TMConfiguration_BGPLSreader_IETFwriter.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/TMConfiguration_BGPLSreader_UNIFYwriter.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/TMConfiguration_COPreader_BGPLSsender.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/TMConfiguration_COPsender.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/log4j2.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/network1_pce.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/total.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/total101.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/main/sample-config-files/examples/total10v2.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/test/java/es/tid/bgp/bgp4Peer/tests/BGP4PeerTest.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/test/resources/BGP4Parameters_1.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/test/resources/BGP4Parameters_1_IT.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/test/resources/BGP4Parameters_2.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/test/resources/EmulatedTopology.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/test/resources/EmulatedTopologyECOC.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/test/resources/log4j2.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/src/test/resources/network1.xml create mode 100644 src/bgpls_speaker/service/java/netphony-topology/target/generated-sources/protobuf/grpc-java/src/main/proto/updateServiceGrpc.java create mode 100644 src/bgpls_speaker/service/java/netphony-topology/topology.iml create mode 100644 src/bgpls_speaker/service/tools/DiscoveredDBManager.py create mode 100644 src/bgpls_speaker/service/tools/GrpcServer.py create mode 100644 src/bgpls_speaker/service/tools/JavaRunner.py create mode 100644 src/bgpls_speaker/service/tools/Tools.py create mode 100644 src/bgpls_speaker/service/tools/__init__.py create mode 100644 src/bgpls_speaker/service/tools/json_loader.py create mode 100644 src/bgpls_speaker/service/tools/protos/grpcService.proto create mode 100644 src/bgpls_speaker/service/tools/protos/grpcService_pb2.py create mode 100644 src/bgpls_speaker/service/tools/protos/grpcService_pb2_grpc.py create mode 100644 src/bgpls_speaker/tests/.gitignore create mode 100644 src/bgpls_speaker/tests/__init__.py create mode 100644 src/bgpls_speaker/tests/test_unitary.py create mode 100644 src/common/tools/context_queries/OpticalConfig.py create mode 100644 src/context/service/database/OpticalConfig.py create mode 100644 src/context/service/database/models/OpticalConfigModel.py create mode 100644 src/context/service/database/models/OpticalLinkModel.py create mode 100644 src/context/service/database/uuids/OpticalConfig.py create mode 100644 src/device/service/OpenConfigServicer.py create mode 100644 src/device/service/drivers/oc_driver/OCDriver.py create mode 100644 src/device/service/drivers/oc_driver/RetryDecorator.py create mode 100644 src/device/service/drivers/oc_driver/Tools.py create mode 100644 src/device/service/drivers/oc_driver/__init__.py create mode 100644 src/device/service/drivers/oc_driver/templates/Interfaces/__init__.py create mode 100644 src/device/service/drivers/oc_driver/templates/Interfaces/interfaces.py create mode 100644 src/device/service/drivers/oc_driver/templates/Tools.py create mode 100644 src/device/service/drivers/oc_driver/templates/VPN/__init__.py create mode 100644 src/device/service/drivers/oc_driver/templates/VPN/physical.py create mode 100644 src/device/service/drivers/oc_driver/templates/__init__.py create mode 100644 src/opticalcontroller/.gitlab-ci.yml create mode 100644 src/opticalcontroller/Dockerfile create mode 100644 src/opticalcontroller/OpticalController.py create mode 100644 src/opticalcontroller/README.md create mode 100644 src/opticalcontroller/RSA.py create mode 100644 src/opticalcontroller/__init__.py create mode 100644 src/opticalcontroller/dijsktra.py create mode 100644 src/opticalcontroller/images/topo.png create mode 100644 src/opticalcontroller/json_files/nodes.json create mode 100644 src/opticalcontroller/json_files/optical_TFSworking.json create mode 100644 src/opticalcontroller/json_files/optical_topoTFS.json create mode 100644 src/opticalcontroller/json_files/tfs.json create mode 100644 src/opticalcontroller/json_files/topo_2_links.json create mode 100644 src/opticalcontroller/json_files/topology-optical.json create mode 100644 src/opticalcontroller/json_files/topology-optical2.json create mode 100644 src/opticalcontroller/requirements.in create mode 100644 src/opticalcontroller/tools.py create mode 100644 src/opticalcontroller/variables.py create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/common/ApplicationProperties.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/exception/ExternalServiceFailureException.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/exception/GeneralExceptionHandler.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/PolicyGateway.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/PolicyGatewayImpl.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/PolicyService.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/PolicyServiceImpl.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/model/BooleanOperator.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/model/NumericalOperator.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/model/PolicyRule.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/model/PolicyRuleAction.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/model/PolicyRuleActionConfig.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/model/PolicyRuleActionEnum.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/model/PolicyRuleBase.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/model/PolicyRuleBasic.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/model/PolicyRuleCondition.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/model/PolicyRuleDevice.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/model/PolicyRuleService.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/model/PolicyRuleState.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/model/PolicyRuleStateEnum.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/model/PolicyRuleType.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/model/PolicyRuleTypeDevice.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/model/PolicyRuleTypeService.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/service/PolicyRuleConditionFieldsGetter.java create mode 100644 src/policy/src/main/java/org/etsi/tfs/policy/policy/service/PolicyRuleConditionValidator.java create mode 100644 src/policy/src/test/java/org/etsi/tfs/policy/PolicyAddDeviceTest.java create mode 100644 src/policy/src/test/java/org/etsi/tfs/policy/PolicyAddServiceTest.java create mode 100644 src/policy/src/test/java/org/etsi/tfs/policy/PolicyDeleteServiceTest.java create mode 100644 src/policy/src/test/java/org/etsi/tfs/policy/PolicyGrpcServiceTest.java create mode 100644 src/policy/src/test/java/org/etsi/tfs/policy/PolicyUpdateDeviceTest.java create mode 100644 src/policy/src/test/java/org/etsi/tfs/policy/PolicyUpdateServiceTest.java create mode 100644 src/service/service/service_handlers/oc/ConfigRules.py create mode 100644 src/service/service/service_handlers/oc/OCServiceHandler.py create mode 100644 src/service/service/service_handlers/oc/OCTools.py create mode 100644 src/service/service/service_handlers/oc/__init__.py create mode 100644 src/service/service/tools/OpticalTools.py create mode 100644 src/service/service/tools/replies.py create mode 100644 src/tests/ecoc22/.gitlab-ci.yml create mode 100644 src/tests/ecoc22/Dockerfile create mode 100644 src/tests/ecoc22/requirements.in create mode 100644 src/tests/ofc22/.gitlab-ci.yml create mode 100644 src/tests/ofc22/Dockerfile create mode 100644 src/tests/ofc22/requirements.in create mode 100644 src/tests/ofc24/.gitlab-ci.yml create mode 100644 src/tests/ofc24/1.context.json create mode 100644 src/tests/ofc24/2.device1.json create mode 100644 src/tests/ofc24/3.device2.json create mode 100644 src/tests/ofc24/4.device3_R1.json create mode 100644 src/tests/ofc24/5.device4_R2.json create mode 100644 src/tests/ofc24/6.links.json create mode 100644 src/tests/ofc24/7.service-bidir.json create mode 100644 src/tests/ofc24/7.service-unidir.json create mode 100644 src/tests/ofc24/Dockerfile create mode 100644 src/tests/ofc24/README.md create mode 100644 src/tests/ofc24/copy.sh create mode 100644 src/tests/ofc24/deploy-node-agents.sh create mode 100644 src/tests/ofc24/deploy_specs.sh create mode 100644 src/tests/ofc24/descriptors_topology.json create mode 100644 src/tests/ofc24/requirements.in create mode 100644 src/tests/ofc24/run_test.sh create mode 100644 src/tests/ofc24/startExtraNetConfigAgent.sh create mode 100644 src/tests/ofc24/start_topo.sh create mode 100644 src/tests/ofc24/tests/__init__.py create mode 100644 src/tests/ofc24/tests/test_functional_bootstrap.py create mode 100644 src/tests/ofc24/tests/test_functional_cleanup.py create mode 100644 src/tests/ofc24/tests/test_functional_create_service.py create mode 100644 src/tests/ofc24/tests/test_functional_delete_service.py create mode 100644 src/webui/service/bgpls/__init__.py create mode 100644 src/webui/service/bgpls/forms.py create mode 100644 src/webui/service/bgpls/routes.py create mode 100644 src/webui/service/opticalconfig/__init__.py create mode 100644 src/webui/service/opticalconfig/forms.py create mode 100644 src/webui/service/opticalconfig/routes.py create mode 100644 src/webui/service/static/topology_icons/p4-switch.png create mode 100644 src/webui/service/templates/bgpls/add.html create mode 100644 src/webui/service/templates/bgpls/addSpeaker.html create mode 100644 src/webui/service/templates/bgpls/editSpeakers.html create mode 100644 src/webui/service/templates/bgpls/home.html create mode 100644 src/webui/service/templates/opticalconfig/add_transceiver.html create mode 100644 src/webui/service/templates/opticalconfig/details.html create mode 100644 src/webui/service/templates/opticalconfig/home.html create mode 100644 src/webui/service/templates/opticalconfig/update_interface.html create mode 100644 src/webui/service/templates/topology/add.html create mode 100644 src/webui/service/templates/topology/addSpeaker.html create mode 100644 src/webui/service/templates/topology/editSpeakers.html create mode 100644 src/webui/service/templates/topology/home.html create mode 100644 src/webui/service/topology/__init__.py create mode 100644 src/webui/service/topology/forms.py create mode 100644 src/webui/service/topology/routes.py create mode 100644 test.py diff --git a/deploy/component.sh b/deploy/component.sh index e26488186..d3a94c259 100755 --- a/deploy/component.sh +++ b/deploy/component.sh @@ -40,6 +40,21 @@ export TFS_GRAFANA_PASSWORD=${TFS_GRAFANA_PASSWORD:-"admin123+"} # Automated steps start here ######################################################################################################################## +DOCKER_BUILD="docker build" +DOCKER_MAJOR_VERSION=$(docker --version | grep -o -E "Docker version [0-9]+\." | grep -o -E "[0-9]+" | cut -c 1-3) +if [[ $DOCKER_MAJOR_VERSION -ge 23 ]]; then + # If Docker version >= 23, build command was migrated to docker-buildx + # In Ubuntu, in practice, means to install package docker-buildx together with docker.io + # Check if docker-buildx plugin is installed + docker buildx version 1>/dev/null 2>/dev/null + if [[ $? -ne 0 ]]; then + echo "Docker buildx command is not installed. Check: https://docs.docker.com/build/architecture/#install-buildx" + echo "If you installed docker through APT package docker.io, consider installing also package docker-buildx" + exit 1; + fi + DOCKER_BUILD="docker buildx build" +fi + # Constants GITLAB_REPO_URL="labs.etsi.org:5050/tfs/controller" TMP_FOLDER="./tmp" @@ -60,17 +75,17 @@ for COMPONENT in $TFS_COMPONENTS; do BUILD_LOG="$TMP_LOGS_FOLDER/build_${COMPONENT}.log" if [ "$COMPONENT" == "ztp" ] || [ "$COMPONENT" == "policy" ]; then - docker build -t "$IMAGE_NAME" -f ./src/"$COMPONENT"/Dockerfile ./src/"$COMPONENT"/ > "$BUILD_LOG" + $DOCKER_BUILD -t "$IMAGE_NAME" -f ./src/"$COMPONENT"/Dockerfile ./src/"$COMPONENT"/ > "$BUILD_LOG" elif [ "$COMPONENT" == "pathcomp" ]; then BUILD_LOG="$TMP_LOGS_FOLDER/build_${COMPONENT}-frontend.log" - docker build -t "$COMPONENT-frontend:$TFS_IMAGE_TAG" -f ./src/"$COMPONENT"/frontend/Dockerfile . >> "$BUILD_LOG" + $DOCKER_BUILD -t "$COMPONENT-frontend:$TFS_IMAGE_TAG" -f ./src/"$COMPONENT"/frontend/Dockerfile . >> "$BUILD_LOG" BUILD_LOG="$TMP_LOGS_FOLDER/build_${COMPONENT}-backend.log" - docker build -t "$COMPONENT-backend:$TFS_IMAGE_TAG" -f ./src/"$COMPONENT"/backend/Dockerfile . >> "$BUILD_LOG" + $DOCKER_BUILD -t "$COMPONENT-backend:$TFS_IMAGE_TAG" -f ./src/"$COMPONENT"/backend/Dockerfile . >> "$BUILD_LOG" # next command is redundant, but helpful to keep cache updated between rebuilds - docker build -t "$COMPONENT-backend:$TFS_IMAGE_TAG-builder" --target builder -f ./src/"$COMPONENT"/backend/Dockerfile . >> "$BUILD_LOG" + $DOCKER_BUILD -t "$COMPONENT-backend:$TFS_IMAGE_TAG-builder" --target builder -f ./src/"$COMPONENT"/backend/Dockerfile . >> "$BUILD_LOG" else - docker build -t "$IMAGE_NAME" -f ./src/"$COMPONENT"/Dockerfile . > "$BUILD_LOG" + $DOCKER_BUILD -t "$IMAGE_NAME" -f ./src/"$COMPONENT"/Dockerfile . > "$BUILD_LOG" fi if [ -n "$TFS_REGISTRY_IMAGES" ]; then diff --git a/deploy/crdb.sh b/deploy/crdb.sh index 5d87adf60..a304e83d1 100755 --- a/deploy/crdb.sh +++ b/deploy/crdb.sh @@ -158,9 +158,19 @@ function crdb_undeploy_single() { function crdb_drop_database_single() { echo "Drop database if exists" - CRDB_PORT_SQL=$(kubectl --namespace ${CRDB_NAMESPACE} get service cockroachdb-public -o 'jsonpath={.spec.ports[?(@.name=="sql")].port}') - CRDB_CLIENT_URL="postgresql://${CRDB_USERNAME}:${CRDB_PASSWORD}@cockroachdb-0:${CRDB_PORT_SQL}/defaultdb?sslmode=require" - kubectl exec -it --namespace ${CRDB_NAMESPACE} cockroachdb-0 -- \ + + if [[ -z "${GITLAB_CI}" ]]; then + #kubectl --namespace ${CRDB_NAMESPACE} get service cockroachdb-public -o yaml + CRDB_HOST=$(kubectl --namespace ${CRDB_NAMESPACE} get service cockroachdb-public -o 'jsonpath={.spec.clusterIP}') + CRDB_PORT=$(kubectl --namespace ${CRDB_NAMESPACE} get service cockroachdb-public -o 'jsonpath={.spec.ports[?(@.name=="sql")].port}') + else + CRDB_HOST="127.0.0.1" + CRDB_PORT=${CRDB_EXT_PORT_SQL} + fi + + CRDB_CLIENT_URL="postgresql://${CRDB_USERNAME}:${CRDB_PASSWORD}@${CRDB_HOST}:${CRDB_PORT}/defaultdb?sslmode=require" + echo "CRDB_CLIENT_URL=${CRDB_CLIENT_URL}" + kubectl exec -i --namespace ${CRDB_NAMESPACE} cockroachdb-0 -- \ ./cockroach sql --certs-dir=/cockroach/cockroach-certs --url=${CRDB_CLIENT_URL} \ --execute "DROP DATABASE IF EXISTS ${CRDB_DATABASE};" echo @@ -343,7 +353,7 @@ function crdb_undeploy_cluster() { function crdb_drop_database_cluster() { echo "Drop database if exists" - kubectl exec -it --namespace ${CRDB_NAMESPACE} cockroachdb-client-secure -- \ + kubectl exec -i --namespace ${CRDB_NAMESPACE} cockroachdb-client-secure -- \ ./cockroach sql --certs-dir=/cockroach/cockroach-certs --host=cockroachdb-public --execute \ "DROP DATABASE IF EXISTS ${CRDB_DATABASE};" echo diff --git a/deploy/mock_blockchain.sh b/deploy/mock_blockchain.sh index 74d62cd52..df8496bea 100755 --- a/deploy/mock_blockchain.sh +++ b/deploy/mock_blockchain.sh @@ -58,9 +58,24 @@ echo "Processing '$COMPONENT' component..." IMAGE_NAME="$COMPONENT:$IMAGE_TAG" IMAGE_URL=$(echo "$REGISTRY_IMAGE/$IMAGE_NAME" | sed 's,//,/,g' | sed 's,http:/,,g') +DOCKER_BUILD="docker build" +DOCKER_MAJOR_VERSION=$(docker --version | grep -o -E "Docker version [0-9]+\." | grep -o -E "[0-9]+" | cut -c 1-3) +if [[ $DOCKER_MAJOR_VERSION -ge 23 ]]; then + # If Docker version >= 23, build command was migrated to docker-buildx + # In Ubuntu, in practice, means to install package docker-buildx together with docker.io + # Check if docker-buildx plugin is installed + docker buildx version 1>/dev/null 2>/dev/null + if [[ $? -ne 0 ]]; then + echo "Docker buildx command is not installed. Check: https://docs.docker.com/build/architecture/#install-buildx" + echo "If you installed docker through APT package docker.io, consider installing also package docker-buildx" + exit 1; + fi + DOCKER_BUILD="docker buildx build" +fi + echo " Building Docker image..." BUILD_LOG="$TMP_LOGS_FOLDER/build_${COMPONENT}.log" -docker build -t "$IMAGE_NAME" -f ./src/dlt/mock_blockchain/Dockerfile . > "$BUILD_LOG" +$DOCKER_BUILD -t "$IMAGE_NAME" -f ./src/dlt/mock_blockchain/Dockerfile . > "$BUILD_LOG" if [ -n "$REGISTRY_IMAGE" ]; then echo " Pushing Docker image to '$REGISTRY_IMAGE'..." diff --git a/deploy/qdb.sh b/deploy/qdb.sh index e930b5a6c..3235c6c82 100755 --- a/deploy/qdb.sh +++ b/deploy/qdb.sh @@ -160,10 +160,17 @@ function qdb_undeploy() { } function qdb_drop_tables() { - QDB_HOST=$(kubectl --namespace ${QDB_NAMESPACE} get service questdb-public -o 'jsonpath={.spec.clusterIP}') - QDB_PORT=$(kubectl --namespace ${QDB_NAMESPACE} get service questdb-public -o 'jsonpath={.spec.ports[?(@.name=="http")].port}') - echo "Drop tables, if exist" + + if [[ -z "${GITLAB_CI}" ]]; then + #kubectl --namespace ${QDB_NAMESPACE} get service questdb-public -o yaml + QDB_HOST=$(kubectl --namespace ${QDB_NAMESPACE} get service questdb-public -o 'jsonpath={.spec.clusterIP}') + QDB_PORT=$(kubectl --namespace ${QDB_NAMESPACE} get service questdb-public -o 'jsonpath={.spec.ports[?(@.name=="http")].port}') + else + QDB_HOST="127.0.0.1" + QDB_PORT=${QDB_EXT_PORT_HTTP} + fi + curl "http://${QDB_HOST}:${QDB_PORT}/exec?fmt=json&query=DROP+TABLE+IF+EXISTS+${QDB_TABLE_MONITORING_KPIS}+;" echo curl "http://${QDB_HOST}:${QDB_PORT}/exec?fmt=json&query=DROP+TABLE+IF+EXISTS+${QDB_TABLE_SLICE_GROUPS}+;" diff --git a/deploy/tfs.sh b/deploy/tfs.sh index 3a01606ce..fd49c9758 100755 --- a/deploy/tfs.sh +++ b/deploy/tfs.sh @@ -299,8 +299,13 @@ for COMPONENT in $TFS_COMPONENTS; do VERSION=$(grep -i "${GITLAB_REPO_URL}/${COMPONENT}-gateway:" "$MANIFEST" | cut -d ":" -f4) sed -E -i "s#image: $GITLAB_REPO_URL/$COMPONENT-gateway:${VERSION}#image: $IMAGE_URL#g" "$MANIFEST" else - IMAGE_URL=$(echo "$TFS_REGISTRY_IMAGES/$COMPONENT:$TFS_IMAGE_TAG" | sed 's,//,/,g' | sed 's,http:/,,g') - VERSION=$(grep -i "${GITLAB_REPO_URL}/${COMPONENT}:" "$MANIFEST" | cut -d ":" -f4) + if [ "$TFS_SKIP_BUILD" != "YES" ]; then + IMAGE_URL=$(echo "$TFS_REGISTRY_IMAGES/$COMPONENT:$TFS_IMAGE_TAG" | sed 's,//,/,g' | sed 's,http:/,,g') + VERSION=$(grep -i "${GITLAB_REPO_URL}/${COMPONENT}:" "$MANIFEST" | cut -d ":" -f4) + else + VERSION=$(grep -i "${GITLAB_REPO_URL}/${COMPONENT}:" "$MANIFEST" | cut -d ":" -f4) + IMAGE_URL=$(echo "$TFS_REGISTRY_IMAGES/$COMPONENT:$VERSION" | sed 's,//,/,g' | sed 's,http:/,,g') + fi sed -E -i "s#image: $GITLAB_REPO_URL/$COMPONENT:${VERSION}#image: $IMAGE_URL#g" "$MANIFEST" fi @@ -364,7 +369,13 @@ for COMPONENT in $TFS_COMPONENTS; do echo "Waiting for '$COMPONENT' component..." COMPONENT_OBJNAME=$(echo "${COMPONENT}" | sed "s/\_/-/") kubectl wait --namespace $TFS_K8S_NAMESPACE \ - --for='condition=available' --timeout=300s deployment/${COMPONENT_OBJNAME}service + --for='condition=available' --timeout=90s deployment/${COMPONENT_OBJNAME}service + WAIT_EXIT_CODE=$? + if [[ $WAIT_EXIT_CODE != 0 ]]; then + echo " Failed to deploy '${COMPONENT}' component, exit code '${WAIT_EXIT_CODE}', exiting..." + kubectl logs --namespace $TFS_K8S_NAMESPACE deployment/${COMPONENT_OBJNAME}service --all-containers=true + exit $WAIT_EXIT_CODE + fi printf "\n" done diff --git a/manifests/bgpls_speakerservice.yaml b/manifests/bgpls_speakerservice.yaml new file mode 100644 index 000000000..bda0d4cf5 --- /dev/null +++ b/manifests/bgpls_speakerservice.yaml @@ -0,0 +1,72 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: bgpls-speakerservice +spec: + selector: + matchLabels: + app: bgpls-speakerservice + replicas: 1 + template: + metadata: + labels: + app: bgpls-speakerservice + spec: + terminationGracePeriodSeconds: 5 + containers: + - name: server + image: localhost:32000/tfs/bgpls_speaker:dev + imagePullPolicy: Always + ports: + - containerPort: 20030 + - containerPort: 9192 + env: + - name: LOG_LEVEL + value: "INFO" + readinessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:20030"] + livenessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:20030"] + resources: + requests: + cpu: 250m + memory: 128Mi + limits: + cpu: 1000m + memory: 1024Mi +--- +apiVersion: v1 +kind: Service +metadata: + name: bgpls-speakerservice + labels: + app: bgpls-speakerservice +spec: + type: ClusterIP + selector: + app: bgpls-speakerservice + ports: + - name: grpc + protocol: TCP + port: 20030 + targetPort: 20030 + - name: metrics + protocol: TCP + port: 9192 + targetPort: 9192 diff --git a/manifests/cachingservice.yaml b/manifests/cachingservice.yaml index be8fced49..ee6e02e00 100644 --- a/manifests/cachingservice.yaml +++ b/manifests/cachingservice.yaml @@ -27,28 +27,28 @@ spec: app: cachingservice spec: containers: - - name: redis - image: redis:7.0-alpine - env: - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: redis-secrets - key: REDIS_PASSWORD - ports: - - containerPort: 6379 - name: client - command: ["redis-server"] - args: - - --requirepass - - $(REDIS_PASSWORD) - resources: - requests: - cpu: 50m - memory: 64Mi - limits: - cpu: 500m - memory: 512Mi + - name: redis + image: redis:7.0-alpine + env: + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: redis-secrets + key: REDIS_PASSWORD + ports: + - containerPort: 6379 + name: client + command: ["redis-server"] + args: + - --requirepass + - $(REDIS_PASSWORD) + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 500m + memory: 512Mi --- apiVersion: v1 kind: Service @@ -59,6 +59,6 @@ spec: selector: app: cachingservice ports: - - name: redis - port: 6379 - targetPort: 6379 + - name: redis + port: 6379 + targetPort: 6379 diff --git a/manifests/contextservice.yaml b/manifests/contextservice.yaml index df06c86b5..c7dc59625 100644 --- a/manifests/contextservice.yaml +++ b/manifests/contextservice.yaml @@ -30,39 +30,39 @@ spec: spec: terminationGracePeriodSeconds: 5 containers: - - name: server - image: labs.etsi.org:5050/tfs/controller/context:latest - imagePullPolicy: Always - ports: - - containerPort: 1010 - - containerPort: 9192 - env: - - name: MB_BACKEND - value: "nats" - - name: LOG_LEVEL - value: "INFO" - - name: ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY - value: "FALSE" - - name: ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY - value: "FALSE" - envFrom: - - secretRef: - name: crdb-data - - secretRef: - name: nats-data - readinessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:1010"] - livenessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:1010"] - resources: - requests: - cpu: 250m - memory: 128Mi - limits: - cpu: 1000m - memory: 1024Mi + - name: server + image: labs.etsi.org:5050/tfs/controller/context:latest + imagePullPolicy: Always + ports: + - containerPort: 1010 + - containerPort: 9192 + env: + - name: MB_BACKEND + value: "nats" + - name: LOG_LEVEL + value: "INFO" + - name: ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY + value: "FALSE" + - name: ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY + value: "FALSE" + envFrom: + - secretRef: + name: crdb-data + - secretRef: + name: nats-data + readinessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:1010"] + livenessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:1010"] + resources: + requests: + cpu: 250m + memory: 128Mi + limits: + cpu: 1000m + memory: 1024Mi --- apiVersion: v1 kind: Service @@ -75,14 +75,14 @@ spec: selector: app: contextservice ports: - - name: grpc - protocol: TCP - port: 1010 - targetPort: 1010 - - name: metrics - protocol: TCP - port: 9192 - targetPort: 9192 + - name: grpc + protocol: TCP + port: 1010 + targetPort: 1010 + - name: metrics + protocol: TCP + port: 9192 + targetPort: 9192 --- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler @@ -96,12 +96,12 @@ spec: minReplicas: 1 maxReplicas: 20 metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 80 + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 80 #behavior: # scaleDown: # stabilizationWindowSeconds: 30 diff --git a/manifests/dbscanservingservice.yaml b/manifests/dbscanservingservice.yaml index b5b8fc437..2bdd1c3fa 100644 --- a/manifests/dbscanservingservice.yaml +++ b/manifests/dbscanservingservice.yaml @@ -27,28 +27,28 @@ spec: spec: terminationGracePeriodSeconds: 5 containers: - - name: server - image: labs.etsi.org:5050/tfs/controller/dbscanserving:latest - imagePullPolicy: Always - ports: - - containerPort: 10008 - - containerPort: 9192 - env: - - name: LOG_LEVEL - value: "INFO" - readinessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10008"] - livenessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10008"] - resources: - requests: - cpu: 250m - memory: 128Mi - limits: - cpu: 1000m - memory: 1024Mi + - name: server + image: labs.etsi.org:5050/tfs/controller/dbscanserving:latest + imagePullPolicy: Always + ports: + - containerPort: 10008 + - containerPort: 9192 + env: + - name: LOG_LEVEL + value: "INFO" + readinessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10008"] + livenessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10008"] + resources: + requests: + cpu: 250m + memory: 128Mi + limits: + cpu: 1000m + memory: 1024Mi --- apiVersion: v1 kind: Service @@ -61,12 +61,12 @@ spec: selector: app: dbscanservingservice ports: - - name: grpc - port: 10008 - targetPort: 10008 - - name: metrics - port: 9192 - targetPort: 9192 + - name: grpc + port: 10008 + targetPort: 10008 + - name: metrics + port: 9192 + targetPort: 9192 --- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler @@ -80,12 +80,12 @@ spec: minReplicas: 1 maxReplicas: 20 metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 80 + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 80 #behavior: # scaleDown: # stabilizationWindowSeconds: 30 diff --git a/manifests/deviceservice.yaml b/manifests/deviceservice.yaml index 77e421f29..fdc3cea02 100644 --- a/manifests/deviceservice.yaml +++ b/manifests/deviceservice.yaml @@ -31,33 +31,33 @@ spec: spec: terminationGracePeriodSeconds: 5 containers: - - name: server - image: labs.etsi.org:5050/tfs/controller/device:latest - imagePullPolicy: Always - ports: - - containerPort: 2020 - - containerPort: 9192 - env: - - name: LOG_LEVEL - value: "INFO" - startupProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:2020"] - failureThreshold: 30 - periodSeconds: 1 - readinessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:2020"] - livenessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:2020"] - resources: - requests: - cpu: 250m - memory: 128Mi - limits: - cpu: 1000m - memory: 1024Mi + - name: server + image: labs.etsi.org:5050/tfs/controller/device:latest + imagePullPolicy: Always + ports: + - containerPort: 2020 + - containerPort: 9192 + env: + - name: LOG_LEVEL + value: "INFO" + startupProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:2020"] + failureThreshold: 30 + periodSeconds: 1 + readinessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:2020"] + livenessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:2020"] + resources: + requests: + cpu: 250m + memory: 128Mi + limits: + cpu: 1000m + memory: 1024Mi --- apiVersion: v1 kind: Service @@ -70,11 +70,11 @@ spec: selector: app: deviceservice ports: - - name: grpc - protocol: TCP - port: 2020 - targetPort: 2020 - - name: metrics - protocol: TCP - port: 9192 - targetPort: 9192 + - name: grpc + protocol: TCP + port: 2020 + targetPort: 2020 + - name: metrics + protocol: TCP + port: 9192 + targetPort: 9192 diff --git a/manifests/dltservice.yaml b/manifests/dltservice.yaml index 5e8f745f7..f905749b4 100644 --- a/manifests/dltservice.yaml +++ b/manifests/dltservice.yaml @@ -27,57 +27,57 @@ spec: spec: terminationGracePeriodSeconds: 5 containers: - - name: connector - image: labs.etsi.org:5050/tfs/controller/dlt-connector:latest - imagePullPolicy: Always - ports: - - containerPort: 8080 - - containerPort: 9192 - env: - - name: LOG_LEVEL - value: "INFO" - ## for debug purposes - #- name: DLT_GATEWAY_HOST - # value: "mock-blockchain.tfs-bchain.svc.cluster.local" - #- name: DLT_GATEWAY_PORT - # value: "50051" - readinessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:8080"] - livenessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:8080"] - resources: - requests: - cpu: 50m - memory: 64Mi - limits: - cpu: 500m - memory: 512Mi - - name: gateway - image: labs.etsi.org:5050/tfs/controller/dlt-gateway:latest - imagePullPolicy: Always - ports: - - containerPort: 50051 - #readinessProbe: - # httpGet: - # path: /health - # port: 8081 - # initialDelaySeconds: 5 - # timeoutSeconds: 5 - #livenessProbe: - # httpGet: - # path: /health - # port: 8081 - # initialDelaySeconds: 5 - # timeoutSeconds: 5 - resources: - requests: - cpu: 200m - memory: 512Mi - limits: - cpu: 700m - memory: 1024Mi + - name: connector + image: labs.etsi.org:5050/tfs/controller/dlt-connector:latest + imagePullPolicy: Always + ports: + - containerPort: 8080 + - containerPort: 9192 + env: + - name: LOG_LEVEL + value: "INFO" + ## for debug purposes + #- name: DLT_GATEWAY_HOST + # value: "mock-blockchain.tfs-bchain.svc.cluster.local" + #- name: DLT_GATEWAY_PORT + # value: "50051" + readinessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:8080"] + livenessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:8080"] + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 500m + memory: 512Mi + - name: gateway + image: labs.etsi.org:5050/tfs/controller/dlt-gateway:latest + imagePullPolicy: Always + ports: + - containerPort: 50051 + #readinessProbe: + # httpGet: + # path: /health + # port: 8081 + # initialDelaySeconds: 5 + # timeoutSeconds: 5 + #livenessProbe: + # httpGet: + # path: /health + # port: 8081 + # initialDelaySeconds: 5 + # timeoutSeconds: 5 + resources: + requests: + cpu: 200m + memory: 512Mi + limits: + cpu: 700m + memory: 1024Mi --- apiVersion: v1 kind: Service @@ -90,11 +90,11 @@ spec: selector: app: dltservice ports: - - name: grpc - protocol: TCP - port: 8080 - targetPort: 8080 - - name: metrics - protocol: TCP - port: 9192 - targetPort: 9192 + - name: grpc + protocol: TCP + port: 8080 + targetPort: 8080 + - name: metrics + protocol: TCP + port: 9192 + targetPort: 9192 diff --git a/manifests/e2e_orchestratorservice.yaml b/manifests/e2e_orchestratorservice.yaml index 899e17fff..90d377711 100644 --- a/manifests/e2e_orchestratorservice.yaml +++ b/manifests/e2e_orchestratorservice.yaml @@ -27,28 +27,28 @@ spec: spec: terminationGracePeriodSeconds: 5 containers: - - name: server - image: labs.etsi.org:5050/tfs/controller/e2e_orchestrator:latest - imagePullPolicy: Always - ports: - - containerPort: 10050 - - containerPort: 9192 - env: - - name: LOG_LEVEL - value: "INFO" - readinessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10050"] - livenessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10050"] - resources: - requests: - cpu: 250m - memory: 128Mi - limits: - cpu: 1000m - memory: 1024Mi + - name: server + image: labs.etsi.org:5050/tfs/controller/e2e_orchestrator:latest + imagePullPolicy: Always + ports: + - containerPort: 10050 + - containerPort: 9192 + env: + - name: LOG_LEVEL + value: "INFO" + readinessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10050"] + livenessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10050"] + resources: + requests: + cpu: 250m + memory: 128Mi + limits: + cpu: 1000m + memory: 1024Mi --- apiVersion: v1 kind: Service @@ -61,12 +61,12 @@ spec: selector: app: e2e-orchestratorservice ports: - - name: grpc - port: 10050 - targetPort: 10050 - - name: metrics - port: 9192 - targetPort: 9192 + - name: grpc + port: 10050 + targetPort: 10050 + - name: metrics + port: 9192 + targetPort: 9192 --- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler @@ -80,12 +80,12 @@ spec: minReplicas: 1 maxReplicas: 20 metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 80 + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 80 #behavior: # scaleDown: # stabilizationWindowSeconds: 30 diff --git a/manifests/forecasterservice.yaml b/manifests/forecasterservice.yaml index 55d4add88..d1136f617 100644 --- a/manifests/forecasterservice.yaml +++ b/manifests/forecasterservice.yaml @@ -28,35 +28,35 @@ spec: spec: terminationGracePeriodSeconds: 5 containers: - - name: server - image: labs.etsi.org:5050/tfs/controller/forecaster:latest - imagePullPolicy: Always - ports: - - containerPort: 10040 - - containerPort: 9192 - env: - - name: LOG_LEVEL - value: "INFO" - - name: FORECAST_TO_HISTORY_RATIO - value: "10" - startupProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10040"] - failureThreshold: 30 - periodSeconds: 1 - readinessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10040"] - livenessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10040"] - resources: - requests: - cpu: 250m - memory: 128Mi - limits: - cpu: 1000m - memory: 1024Mi + - name: server + image: labs.etsi.org:5050/tfs/controller/forecaster:latest + imagePullPolicy: Always + ports: + - containerPort: 10040 + - containerPort: 9192 + env: + - name: LOG_LEVEL + value: "INFO" + - name: FORECAST_TO_HISTORY_RATIO + value: "10" + startupProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10040"] + failureThreshold: 30 + periodSeconds: 1 + readinessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10040"] + livenessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10040"] + resources: + requests: + cpu: 250m + memory: 128Mi + limits: + cpu: 1000m + memory: 1024Mi --- apiVersion: v1 kind: Service @@ -69,14 +69,14 @@ spec: selector: app: forecasterservice ports: - - name: grpc - protocol: TCP - port: 10040 - targetPort: 10040 - - name: metrics - protocol: TCP - port: 9192 - targetPort: 9192 + - name: grpc + protocol: TCP + port: 10040 + targetPort: 10040 + - name: metrics + protocol: TCP + port: 9192 + targetPort: 9192 --- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler @@ -90,12 +90,12 @@ spec: minReplicas: 1 maxReplicas: 20 metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 80 + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 80 #behavior: # scaleDown: # stabilizationWindowSeconds: 30 diff --git a/manifests/interdomainservice.yaml b/manifests/interdomainservice.yaml index a23583402..ad9be3a3e 100644 --- a/manifests/interdomainservice.yaml +++ b/manifests/interdomainservice.yaml @@ -27,30 +27,30 @@ spec: spec: terminationGracePeriodSeconds: 5 containers: - - name: server - image: labs.etsi.org:5050/tfs/controller/interdomain:latest - imagePullPolicy: Always - ports: - - containerPort: 10010 - - containerPort: 9192 - env: - - name: LOG_LEVEL - value: "INFO" - - name: TOPOLOGY_ABSTRACTOR - value: "DISABLE" - readinessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10010"] - livenessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10010"] - resources: - requests: - cpu: 250m - memory: 64Mi - limits: - cpu: 1000m - memory: 1024Mi + - name: server + image: labs.etsi.org:5050/tfs/controller/interdomain:latest + imagePullPolicy: Always + ports: + - containerPort: 10010 + - containerPort: 9192 + env: + - name: LOG_LEVEL + value: "INFO" + - name: TOPOLOGY_ABSTRACTOR + value: "DISABLE" + readinessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10010"] + livenessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10010"] + resources: + requests: + cpu: 250m + memory: 64Mi + limits: + cpu: 1000m + memory: 1024Mi --- apiVersion: v1 kind: Service @@ -63,11 +63,11 @@ spec: selector: app: interdomainservice ports: - - name: grpc - protocol: TCP - port: 10010 - targetPort: 10010 - - name: metrics - protocol: TCP - port: 9192 - targetPort: 9192 + - name: grpc + protocol: TCP + port: 10010 + targetPort: 10010 + - name: metrics + protocol: TCP + port: 9192 + targetPort: 9192 diff --git a/manifests/l3_attackmitigatorservice.yaml b/manifests/l3_attackmitigatorservice.yaml index ee97d2c92..973b805bd 100644 --- a/manifests/l3_attackmitigatorservice.yaml +++ b/manifests/l3_attackmitigatorservice.yaml @@ -27,28 +27,28 @@ spec: spec: terminationGracePeriodSeconds: 5 containers: - - name: server - image: labs.etsi.org:5050/tfs/controller/l3_attackmitigator:latest - imagePullPolicy: Always - ports: - - containerPort: 10002 - - containerPort: 9192 - env: - - name: LOG_LEVEL - value: "DEBUG" - readinessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10002"] - livenessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10002"] - resources: - requests: - cpu: 250m - memory: 512Mi - limits: - cpu: 700m - memory: 1024Mi + - name: server + image: labs.etsi.org:5050/tfs/controller/l3_attackmitigator:latest + imagePullPolicy: Always + ports: + - containerPort: 10002 + - containerPort: 9192 + env: + - name: LOG_LEVEL + value: "INFO" + readinessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10002"] + livenessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10002"] + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 700m + memory: 1024Mi --- apiVersion: v1 kind: Service @@ -61,13 +61,13 @@ spec: selector: app: l3-attackmitigatorservice ports: - - name: metrics - protocol: TCP - port: 9192 - targetPort: 9192 - - name: grpc - port: 10002 - targetPort: 10002 + - name: metrics + protocol: TCP + port: 9192 + targetPort: 9192 + - name: grpc + port: 10002 + targetPort: 10002 --- apiVersion: autoscaling/v2 @@ -82,12 +82,12 @@ spec: minReplicas: 1 maxReplicas: 10 metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 80 + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 80 behavior: scaleDown: stabilizationWindowSeconds: 120 @@ -100,9 +100,9 @@ metadata: labels: app: l3-attackmitigatorservice #release: prometheus - #release: prom # name of the release - # ( VERY IMPORTANT: You need to know the correct release name by viewing - # the servicemonitor of Prometheus itself: Without the correct name, + #release: prom # name of the release + # ( VERY IMPORTANT: You need to know the correct release name by viewing + # the servicemonitor of Prometheus itself: Without the correct name, # Prometheus cannot identify the metrics of the Flask app as the target.) spec: selector: @@ -112,11 +112,11 @@ spec: app: l3-attackmitigatorservice # same as above #release: prometheus # same as above endpoints: - - port: metrics # named port in target app - scheme: http - path: /metrics # path to scrape - interval: 5s # scrape interval + - port: metrics # named port in target app + scheme: http + path: /metrics # path to scrape + interval: 5s # scrape interval namespaceSelector: any: false matchNames: - - tfs # namespace where the app is running + - tfs # namespace where the app is running diff --git a/manifests/l3_centralizedattackdetectorservice.yaml b/manifests/l3_centralizedattackdetectorservice.yaml index 8a3be69b6..98c5f9b41 100644 --- a/manifests/l3_centralizedattackdetectorservice.yaml +++ b/manifests/l3_centralizedattackdetectorservice.yaml @@ -27,36 +27,36 @@ spec: spec: terminationGracePeriodSeconds: 5 containers: - - name: server - image: labs.etsi.org:5050/tfs/controller/l3_centralizedattackdetector:latest - imagePullPolicy: Always - ports: - - containerPort: 10001 - - containerPort: 9192 - env: - - name: LOG_LEVEL - value: "DEBUG" - - name: BATCH_SIZE - value: "256" - - name: CAD_CLASSIFICATION_THRESHOLD - value: "0.5" - - name: MONITORED_KPIS_TIME_INTERVAL_AGG - value: "60" - - name: TEST_ML_MODEL - value: "0" - readinessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10001"] - livenessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10001"] - resources: - requests: - cpu: 250m - memory: 512Mi - limits: - cpu: 700m - memory: 1024Mi + - name: server + image: labs.etsi.org:5050/tfs/controller/l3_centralizedattackdetector:latest + imagePullPolicy: Always + ports: + - containerPort: 10001 + - containerPort: 9192 + env: + - name: LOG_LEVEL + value: "INFO" + - name: BATCH_SIZE + value: "256" + - name: CAD_CLASSIFICATION_THRESHOLD + value: "0.5" + - name: MONITORED_KPIS_TIME_INTERVAL_AGG + value: "60" + - name: TEST_ML_MODEL + value: "0" + readinessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10001"] + livenessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10001"] + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 700m + memory: 1024Mi --- apiVersion: v1 kind: Service @@ -69,13 +69,13 @@ spec: selector: app: l3-centralizedattackdetectorservice ports: - - name: metrics - protocol: TCP - port: 9192 - targetPort: 9192 - - name: grpc - port: 10001 - targetPort: 10001 + - name: metrics + protocol: TCP + port: 9192 + targetPort: 9192 + - name: grpc + port: 10001 + targetPort: 10001 --- apiVersion: autoscaling/v2 @@ -90,12 +90,12 @@ spec: minReplicas: 1 maxReplicas: 10 metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 80 + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 80 behavior: scaleDown: stabilizationWindowSeconds: 120 @@ -107,9 +107,9 @@ metadata: labels: app: l3-centralizedattackdetectorservice #release: prometheus - #release: prom # name of the release - # ( VERY IMPORTANT: You need to know the correct release name by viewing - # the servicemonitor of Prometheus itself: Without the correct name, + #release: prom # name of the release + # ( VERY IMPORTANT: You need to know the correct release name by viewing + # the servicemonitor of Prometheus itself: Without the correct name, # Prometheus cannot identify the metrics of the Flask app as the target.) spec: selector: @@ -119,11 +119,11 @@ spec: app: l3-centralizedattackdetectorservice # same as above #release: prometheus # same as above endpoints: - - port: metrics # named port in target app - scheme: http - path: /metrics # path to scrape - interval: 5s # scrape interval + - port: metrics # named port in target app + scheme: http + path: /metrics # path to scrape + interval: 5s # scrape interval namespaceSelector: any: false matchNames: - - tfs # namespace where the app is running + - tfs # namespace where the app is running diff --git a/manifests/l3_distributedattackdetectorservice.yaml b/manifests/l3_distributedattackdetectorservice.yaml index b363c1d5c..bf72b5cd0 100644 --- a/manifests/l3_distributedattackdetectorservice.yaml +++ b/manifests/l3_distributedattackdetectorservice.yaml @@ -27,27 +27,27 @@ spec: spec: terminationGracePeriodSeconds: 5 containers: - - name: server - image: labs.etsi.org:5050/tfs/controller/l3_distributedattackdetector:latest - imagePullPolicy: Always - ports: - - containerPort: 10000 - env: - - name: LOG_LEVEL - value: "DEBUG" - readinessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10000"] - livenessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10000"] - resources: - requests: - cpu: 250m - memory: 512Mi - limits: - cpu: 700m - memory: 1024Mi + - name: server + image: labs.etsi.org:5050/tfs/controller/l3_distributedattackdetector:latest + imagePullPolicy: Always + ports: + - containerPort: 10000 + env: + - name: LOG_LEVEL + value: "INFO" + readinessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10000"] + livenessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10000"] + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 700m + memory: 1024Mi --- apiVersion: v1 kind: Service @@ -58,6 +58,6 @@ spec: selector: app: l3-distributedattackdetectorservice ports: - - name: grpc - port: 10000 - targetPort: 10000 + - name: grpc + port: 10000 + targetPort: 10000 diff --git a/manifests/load_generatorservice.yaml b/manifests/load_generatorservice.yaml index 7cc6f1912..bda284ebd 100644 --- a/manifests/load_generatorservice.yaml +++ b/manifests/load_generatorservice.yaml @@ -28,28 +28,28 @@ spec: spec: terminationGracePeriodSeconds: 5 containers: - - name: server - image: labs.etsi.org:5050/tfs/controller/load_generator:latest - imagePullPolicy: Always - ports: - - containerPort: 50052 - - containerPort: 9192 - env: - - name: LOG_LEVEL - value: "INFO" - readinessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:50052"] - livenessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:50052"] - resources: - requests: - cpu: 256m - memory: 64Mi - limits: - cpu: 512m - memory: 128Mi + - name: server + image: labs.etsi.org:5050/tfs/controller/load_generator:latest + imagePullPolicy: Always + ports: + - containerPort: 50052 + - containerPort: 9192 + env: + - name: LOG_LEVEL + value: "INFO" + readinessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:50052"] + livenessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:50052"] + resources: + requests: + cpu: 256m + memory: 64Mi + limits: + cpu: 512m + memory: 128Mi --- apiVersion: v1 kind: Service @@ -62,11 +62,11 @@ spec: selector: app: load-generatorservice ports: - - name: grpc - protocol: TCP - port: 50052 - targetPort: 50052 - - name: metrics - protocol: TCP - port: 9192 - targetPort: 9192 + - name: grpc + protocol: TCP + port: 50052 + targetPort: 50052 + - name: metrics + protocol: TCP + port: 9192 + targetPort: 9192 diff --git a/manifests/mock_blockchain.yaml b/manifests/mock_blockchain.yaml index 1093610f8..806432be6 100644 --- a/manifests/mock_blockchain.yaml +++ b/manifests/mock_blockchain.yaml @@ -27,27 +27,27 @@ spec: spec: terminationGracePeriodSeconds: 5 containers: - - name: server - image: labs.etsi.org:5050/tfs/controller/mock_blockchain:latest - imagePullPolicy: Always - ports: - - containerPort: 50051 - env: - - name: LOG_LEVEL - value: "INFO" - readinessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:50051"] - livenessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:50051"] - resources: - requests: - cpu: 100m - memory: 512Mi - limits: - cpu: 700m - memory: 1024Mi + - name: server + image: labs.etsi.org:5050/tfs/controller/mock_blockchain:latest + imagePullPolicy: Always + ports: + - containerPort: 50051 + env: + - name: LOG_LEVEL + value: "INFO" + readinessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:50051"] + livenessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:50051"] + resources: + requests: + cpu: 100m + memory: 512Mi + limits: + cpu: 700m + memory: 1024Mi --- apiVersion: v1 kind: Service @@ -58,7 +58,7 @@ spec: selector: app: mock-blockchain ports: - - name: grpc - protocol: TCP - port: 50051 - targetPort: 50051 + - name: grpc + protocol: TCP + port: 50051 + targetPort: 50051 diff --git a/manifests/monitoringservice.yaml b/manifests/monitoringservice.yaml index dbcfa68a0..3a4d43cd9 100644 --- a/manifests/monitoringservice.yaml +++ b/manifests/monitoringservice.yaml @@ -28,31 +28,31 @@ spec: spec: terminationGracePeriodSeconds: 5 containers: - - name: server - image: labs.etsi.org:5050/tfs/controller/monitoring:latest - imagePullPolicy: Always - ports: - - containerPort: 7070 - - containerPort: 9192 - env: - - name: LOG_LEVEL - value: "INFO" - envFrom: - - secretRef: - name: qdb-data - readinessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:7070"] - livenessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:7070"] - resources: - requests: - cpu: 250m - memory: 256Mi - limits: - cpu: 1000m - memory: 1024Mi + - name: server + image: labs.etsi.org:5050/tfs/controller/monitoring:latest + imagePullPolicy: Always + ports: + - containerPort: 7070 + - containerPort: 9192 + env: + - name: LOG_LEVEL + value: "INFO" + envFrom: + - secretRef: + name: qdb-data + readinessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:7070"] + livenessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:7070"] + resources: + requests: + cpu: 250m + memory: 256Mi + limits: + cpu: 1000m + memory: 1024Mi --- apiVersion: v1 kind: Service @@ -65,11 +65,11 @@ spec: selector: app: monitoringservice ports: - - name: grpc - protocol: TCP - port: 7070 - targetPort: 7070 - - name: metrics - protocol: TCP - port: 9192 - targetPort: 9192 + - name: grpc + protocol: TCP + port: 7070 + targetPort: 7070 + - name: metrics + protocol: TCP + port: 9192 + targetPort: 9192 diff --git a/manifests/nbiservice.yaml b/manifests/nbiservice.yaml index de97ba364..0a3bd1ea6 100644 --- a/manifests/nbiservice.yaml +++ b/manifests/nbiservice.yaml @@ -28,29 +28,29 @@ spec: spec: terminationGracePeriodSeconds: 5 containers: - - name: server - image: labs.etsi.org:5050/tfs/controller/nbi:latest - imagePullPolicy: Always - ports: - - containerPort: 8080 - - containerPort: 9090 - - containerPort: 9192 - env: - - name: LOG_LEVEL - value: "INFO" - readinessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:9090"] - livenessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:9090"] - resources: - requests: - cpu: 50m - memory: 64Mi - limits: - cpu: 500m - memory: 512Mi + - name: server + image: labs.etsi.org:5050/tfs/controller/nbi:latest + imagePullPolicy: Always + ports: + - containerPort: 8080 + - containerPort: 9090 + - containerPort: 9192 + env: + - name: LOG_LEVEL + value: "INFO" + readinessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:9090"] + livenessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:9090"] + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 500m + memory: 512Mi --- apiVersion: v1 kind: Service @@ -63,15 +63,15 @@ spec: selector: app: nbiservice ports: - - name: http - protocol: TCP - port: 8080 - targetPort: 8080 - - name: grpc - protocol: TCP - port: 9090 - targetPort: 9090 - - name: metrics - protocol: TCP - port: 9192 - targetPort: 9192 + - name: http + protocol: TCP + port: 8080 + targetPort: 8080 + - name: grpc + protocol: TCP + port: 9090 + targetPort: 9090 + - name: metrics + protocol: TCP + port: 9192 + targetPort: 9192 diff --git a/manifests/nginx_ingress_http.yaml b/manifests/nginx_ingress_http.yaml index e8e8a80e4..91440fb7a 100644 --- a/manifests/nginx_ingress_http.yaml +++ b/manifests/nginx_ingress_http.yaml @@ -20,40 +20,40 @@ metadata: nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: rules: - - http: - paths: - - path: /webui(/|$)(.*) - pathType: Prefix - backend: - service: - name: webuiservice - port: - number: 8004 - - path: /grafana(/|$)(.*) - pathType: Prefix - backend: - service: - name: webuiservice - port: - number: 3000 - - path: /()(restconf/.*) - pathType: Prefix - backend: - service: - name: nbiservice - port: - number: 8080 - - path: /()(debug-api/.*) - pathType: Prefix - backend: - service: - name: nbiservice - port: - number: 8080 - - path: /()(bmw/.*) - pathType: Prefix - backend: - service: - name: nbiservice - port: - number: 8080 + - http: + paths: + - path: /webui(/|$)(.*) + pathType: Prefix + backend: + service: + name: webuiservice + port: + number: 8004 + - path: /grafana(/|$)(.*) + pathType: Prefix + backend: + service: + name: webuiservice + port: + number: 3000 + - path: /()(restconf/.*) + pathType: Prefix + backend: + service: + name: nbiservice + port: + number: 8080 + - path: /()(debug-api/.*) + pathType: Prefix + backend: + service: + name: nbiservice + port: + number: 8080 + - path: /()(bmw/.*) + pathType: Prefix + backend: + service: + name: nbiservice + port: + number: 8080 diff --git a/manifests/opticalattackdetectorservice.yaml b/manifests/opticalattackdetectorservice.yaml index 197c23dd2..11fd62b61 100644 --- a/manifests/opticalattackdetectorservice.yaml +++ b/manifests/opticalattackdetectorservice.yaml @@ -27,33 +27,33 @@ spec: spec: terminationGracePeriodSeconds: 5 containers: - - name: server - image: labs.etsi.org:5050/tfs/controller/opticalattackdetector:latest - imagePullPolicy: Always - ports: - - containerPort: 10006 - - containerPort: 9192 - env: - - name: LOG_LEVEL - value: "INFO" - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: redis-secrets - key: REDIS_PASSWORD - readinessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10006"] - livenessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10006"] - resources: - requests: - cpu: 250m - memory: 128Mi - limits: - cpu: 1000m - memory: 1024Mi + - name: server + image: labs.etsi.org:5050/tfs/controller/opticalattackdetector:latest + imagePullPolicy: Always + ports: + - containerPort: 10006 + - containerPort: 9192 + env: + - name: LOG_LEVEL + value: "INFO" + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: redis-secrets + key: REDIS_PASSWORD + readinessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10006"] + livenessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10006"] + resources: + requests: + cpu: 250m + memory: 128Mi + limits: + cpu: 1000m + memory: 1024Mi --- apiVersion: v1 kind: Service @@ -66,12 +66,12 @@ spec: selector: app: opticalattackdetectorservice ports: - - name: grpc - port: 10006 - targetPort: 10006 - - name: metrics - port: 9192 - targetPort: 9192 + - name: grpc + port: 10006 + targetPort: 10006 + - name: metrics + port: 9192 + targetPort: 9192 --- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler @@ -85,12 +85,12 @@ spec: minReplicas: 1 maxReplicas: 20 metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 80 + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 80 #behavior: # scaleDown: # stabilizationWindowSeconds: 30 diff --git a/manifests/opticalattackmanagerservice.yaml b/manifests/opticalattackmanagerservice.yaml index f9838bcbb..4e01d76ac 100644 --- a/manifests/opticalattackmanagerservice.yaml +++ b/manifests/opticalattackmanagerservice.yaml @@ -28,33 +28,33 @@ spec: spec: terminationGracePeriodSeconds: 5 containers: - - name: server - image: labs.etsi.org:5050/tfs/controller/opticalattackmanager:latest - imagePullPolicy: Always - ports: - - containerPort: 10005 - - containerPort: 9192 - env: - - name: LOG_LEVEL - value: "INFO" - - name: MONITORING_INTERVAL - value: "30" - - name: OPTICALATTACKMANAGERSERVICE_LOOP_MIN_WORKERS - value: "2" # remember to align this with the resource limits - - name: OPTICALATTACKMANAGERSERVICE_LOOP_MAX_WORKERS - value: "10" # remember to align this with the resource limits - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: redis-secrets - key: REDIS_PASSWORD - resources: - requests: - cpu: 250m - memory: 128Mi - limits: - cpu: 10000m - memory: 10240Mi + - name: server + image: labs.etsi.org:5050/tfs/controller/opticalattackmanager:latest + imagePullPolicy: Always + ports: + - containerPort: 10005 + - containerPort: 9192 + env: + - name: LOG_LEVEL + value: "INFO" + - name: MONITORING_INTERVAL + value: "30" + - name: OPTICALATTACKMANAGERSERVICE_LOOP_MIN_WORKERS + value: "2" # remember to align this with the resource limits + - name: OPTICALATTACKMANAGERSERVICE_LOOP_MAX_WORKERS + value: "10" # remember to align this with the resource limits + - name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: redis-secrets + key: REDIS_PASSWORD + resources: + requests: + cpu: 250m + memory: 128Mi + limits: + cpu: 10000m + memory: 10240Mi --- apiVersion: v1 kind: Service @@ -67,9 +67,9 @@ spec: selector: app: opticalattackmanagerservice ports: - - name: grpc - port: 10005 - targetPort: 10005 - - name: metrics - port: 9192 - targetPort: 9192 + - name: grpc + port: 10005 + targetPort: 10005 + - name: metrics + port: 9192 + targetPort: 9192 diff --git a/manifests/opticalattackmitigatorservice.yaml b/manifests/opticalattackmitigatorservice.yaml index 4d148b347..255e0fd86 100644 --- a/manifests/opticalattackmitigatorservice.yaml +++ b/manifests/opticalattackmitigatorservice.yaml @@ -27,28 +27,28 @@ spec: spec: terminationGracePeriodSeconds: 5 containers: - - name: server - image: labs.etsi.org:5050/tfs/controller/opticalattackmitigator:latest - imagePullPolicy: Always - ports: - - containerPort: 10007 - - containerPort: 9192 - env: - - name: LOG_LEVEL - value: "INFO" - readinessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10007"] - livenessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10007"] - resources: - requests: - cpu: 250m - memory: 128Mi - limits: - cpu: 1000m - memory: 1024Mi + - name: server + image: labs.etsi.org:5050/tfs/controller/opticalattackmitigator:latest + imagePullPolicy: Always + ports: + - containerPort: 10007 + - containerPort: 9192 + env: + - name: LOG_LEVEL + value: "INFO" + readinessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10007"] + livenessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10007"] + resources: + requests: + cpu: 250m + memory: 128Mi + limits: + cpu: 1000m + memory: 1024Mi --- apiVersion: v1 kind: Service @@ -61,12 +61,12 @@ spec: selector: app: opticalattackmitigatorservice ports: - - name: grpc - port: 10007 - targetPort: 10007 - - name: metrics - port: 9192 - targetPort: 9192 + - name: grpc + port: 10007 + targetPort: 10007 + - name: metrics + port: 9192 + targetPort: 9192 --- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler @@ -80,12 +80,12 @@ spec: minReplicas: 1 maxReplicas: 20 metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 80 + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 80 #behavior: # scaleDown: # stabilizationWindowSeconds: 30 diff --git a/manifests/opticalcontrollerservice.yaml b/manifests/opticalcontrollerservice.yaml new file mode 100644 index 000000000..f2351720c --- /dev/null +++ b/manifests/opticalcontrollerservice.yaml @@ -0,0 +1,72 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: opticalcontrollerservice +spec: + selector: + matchLabels: + app: opticalcontrollerservice + replicas: 1 + template: + metadata: + labels: + app: opticalcontrollerservice + spec: + terminationGracePeriodSeconds: 5 + containers: + - name: server + image: localhost:32000/tfs/opticalcontroller:dev + imagePullPolicy: Never + ports: + - containerPort: 10060 + - containerPort: 9192 + env: + - name: LOG_LEVEL + value: "INFO" + #readinessProbe: + # exec: + # command: ["/bin/grpc_health_probe", "-addr=:10060"] + #livenessProbe: + # exec: + # command: ["/bin/grpc_health_probe", "-addr=:10060"] + resources: + requests: + cpu: 500m + memory: 128Mi + limits: + cpu: 1000m + memory: 1024Mi +--- +apiVersion: v1 +kind: Service +metadata: + name: opticalcontrollerservice + labels: + app: opticalcontrollerservice +spec: + type: ClusterIP + selector: + app: opticalcontrollerservice + ports: + - name: grpc + protocol: TCP + port: 10060 + targetPort: 10060 + - name: metrics + protocol: TCP + port: 9192 + targetPort: 9192 diff --git a/manifests/pathcompservice.yaml b/manifests/pathcompservice.yaml index 87d907a72..f017e6940 100644 --- a/manifests/pathcompservice.yaml +++ b/manifests/pathcompservice.yaml @@ -28,54 +28,54 @@ spec: spec: terminationGracePeriodSeconds: 5 containers: - - name: frontend - image: labs.etsi.org:5050/tfs/controller/pathcomp-frontend:latest - imagePullPolicy: Always - ports: - - containerPort: 10020 - - containerPort: 9192 - env: - - name: LOG_LEVEL - value: "INFO" - - name: ENABLE_FORECASTER - value: "YES" - readinessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10020"] - livenessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:10020"] - resources: - requests: - cpu: 250m - memory: 128Mi - limits: - cpu: 1000m - memory: 1024Mi - - name: backend - image: labs.etsi.org:5050/tfs/controller/pathcomp-backend:latest - imagePullPolicy: Always - ports: - - containerPort: 8081 - #readinessProbe: - # httpGet: - # path: /health - # port: 8081 - # initialDelaySeconds: 5 - # timeoutSeconds: 5 - #livenessProbe: - # httpGet: - # path: /health - # port: 8081 - # initialDelaySeconds: 5 - # timeoutSeconds: 5 - resources: - requests: - cpu: 250m - memory: 256Mi - limits: - cpu: 1000m - memory: 1024Mi + - name: frontend + image: labs.etsi.org:5050/tfs/controller/pathcomp-frontend:latest + imagePullPolicy: Always + ports: + - containerPort: 10020 + - containerPort: 9192 + env: + - name: LOG_LEVEL + value: "INFO" + - name: ENABLE_FORECASTER + value: "NO" + readinessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10020"] + livenessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:10020"] + resources: + requests: + cpu: 250m + memory: 128Mi + limits: + cpu: 1000m + memory: 1024Mi + - name: backend + image: labs.etsi.org:5050/tfs/controller/pathcomp-backend:latest + imagePullPolicy: Always + ports: + - containerPort: 8081 + #readinessProbe: + # httpGet: + # path: /health + # port: 8081 + # initialDelaySeconds: 5 + # timeoutSeconds: 5 + #livenessProbe: + # httpGet: + # path: /health + # port: 8081 + # initialDelaySeconds: 5 + # timeoutSeconds: 5 + resources: + requests: + cpu: 250m + memory: 256Mi + limits: + cpu: 1000m + memory: 1024Mi --- apiVersion: v1 kind: Service @@ -88,18 +88,18 @@ spec: selector: app: pathcompservice ports: - - name: grpc - protocol: TCP - port: 10020 - targetPort: 10020 - - name: http - protocol: TCP - port: 8081 - targetPort: 8081 - - name: metrics - protocol: TCP - port: 9192 - targetPort: 9192 + - name: grpc + protocol: TCP + port: 10020 + targetPort: 10020 + - name: http + protocol: TCP + port: 8081 + targetPort: 8081 + - name: metrics + protocol: TCP + port: 9192 + targetPort: 9192 --- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler @@ -113,12 +113,12 @@ spec: minReplicas: 1 maxReplicas: 20 metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 80 + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 80 #behavior: # scaleDown: # stabilizationWindowSeconds: 30 diff --git a/manifests/policyservice.yaml b/manifests/policyservice.yaml index b34331724..7ef040e7f 100644 --- a/manifests/policyservice.yaml +++ b/manifests/policyservice.yaml @@ -108,22 +108,22 @@ spec: limits: cpu: 2000m memory: 2048Mi ---- -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: policyservice-hpa -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: policyservice - minReplicas: 1 - maxReplicas: 10 - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 80 +#--- +#apiVersion: autoscaling/v2 +#kind: HorizontalPodAutoscaler +#metadata: +# name: policyservice-hpa +#spec: +# scaleTargetRef: +# apiVersion: apps/v1 +# kind: Deployment +# name: policyservice +# minReplicas: 1 +# maxReplicas: 10 +# metrics: +# - type: Resource +# resource: +# name: cpu +# target: +# type: Utilization +# averageUtilization: 80 diff --git a/manifests/prometheus.yaml b/manifests/prometheus.yaml index 43a766b6e..ec1ffb0c5 100644 --- a/manifests/prometheus.yaml +++ b/manifests/prometheus.yaml @@ -60,18 +60,18 @@ spec: spec: #serviceAccountName: prometheus containers: - - name: prometheus - image: prom/prometheus:v2.28.1 - ports: - - containerPort: 9090 - volumeMounts: - - name: prometheus-config-volume - mountPath: /etc/prometheus/prometheus.yml - subPath: prometheus.yml + - name: prometheus + image: prom/prometheus:v2.28.1 + ports: + - containerPort: 9090 + volumeMounts: + - name: prometheus-config-volume + mountPath: /etc/prometheus/prometheus.yml + subPath: prometheus.yml volumes: - - name: prometheus-config-volume - configMap: - name: prometheus-config + - name: prometheus-config-volume + configMap: + name: prometheus-config restartPolicy: Always --- apiVersion: v1 @@ -85,8 +85,9 @@ spec: selector: app: prometheus ports: - - name: http - protocol: TCP - port: 9090 - targetPort: 9090 + - name: http + protocol: TCP + port: 9090 + targetPort: 9090 --- + diff --git a/manifests/servicemonitors.yaml b/manifests/servicemonitors.yaml index 1f7f3322d..ccfe774b3 100644 --- a/manifests/servicemonitors.yaml +++ b/manifests/servicemonitors.yaml @@ -20,9 +20,9 @@ metadata: labels: app: contextservice #release: prometheus - #release: prom # name of the release - # ( VERY IMPORTANT: You need to know the correct release name by viewing - # the servicemonitor of Prometheus itself: Without the correct name, + #release: prom # name of the release + # ( VERY IMPORTANT: You need to know the correct release name by viewing + # the servicemonitor of Prometheus itself: Without the correct name, # Prometheus cannot identify the metrics of the Flask app as the target.) spec: selector: @@ -32,14 +32,14 @@ spec: app: contextservice # same as above #release: prometheus # same as above endpoints: - - port: metrics # named port in target app - scheme: http - path: /metrics # path to scrape - interval: 5s # scrape interval + - port: metrics # named port in target app + scheme: http + path: /metrics # path to scrape + interval: 5s # scrape interval namespaceSelector: any: false matchNames: - - tfs # namespace where the app is running + - tfs # namespace where the app is running --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor @@ -49,9 +49,9 @@ metadata: labels: app: deviceservice #release: prometheus - #release: prom # name of the release - # ( VERY IMPORTANT: You need to know the correct release name by viewing - # the servicemonitor of Prometheus itself: Without the correct name, + #release: prom # name of the release + # ( VERY IMPORTANT: You need to know the correct release name by viewing + # the servicemonitor of Prometheus itself: Without the correct name, # Prometheus cannot identify the metrics of the Flask app as the target.) spec: selector: @@ -61,14 +61,14 @@ spec: app: deviceservice # same as above #release: prometheus # same as above endpoints: - - port: metrics # named port in target app - scheme: http - path: /metrics # path to scrape - interval: 5s # scrape interval + - port: metrics # named port in target app + scheme: http + path: /metrics # path to scrape + interval: 5s # scrape interval namespaceSelector: any: false matchNames: - - tfs # namespace where the app is running + - tfs # namespace where the app is running --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor @@ -78,9 +78,9 @@ metadata: labels: app: serviceservice #release: prometheus - #release: prom # name of the release - # ( VERY IMPORTANT: You need to know the correct release name by viewing - # the servicemonitor of Prometheus itself: Without the correct name, + #release: prom # name of the release + # ( VERY IMPORTANT: You need to know the correct release name by viewing + # the servicemonitor of Prometheus itself: Without the correct name, # Prometheus cannot identify the metrics of the Flask app as the target.) spec: selector: @@ -90,14 +90,14 @@ spec: app: serviceservice # same as above #release: prometheus # same as above endpoints: - - port: metrics # named port in target app - scheme: http - path: /metrics # path to scrape - interval: 5s # scrape interval + - port: metrics # named port in target app + scheme: http + path: /metrics # path to scrape + interval: 5s # scrape interval namespaceSelector: any: false matchNames: - - tfs # namespace where the app is running + - tfs # namespace where the app is running --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor @@ -107,9 +107,9 @@ metadata: labels: app: sliceservice #release: prometheus - #release: prom # name of the release - # ( VERY IMPORTANT: You need to know the correct release name by viewing - # the servicemonitor of Prometheus itself: Without the correct name, + #release: prom # name of the release + # ( VERY IMPORTANT: You need to know the correct release name by viewing + # the servicemonitor of Prometheus itself: Without the correct name, # Prometheus cannot identify the metrics of the Flask app as the target.) spec: selector: @@ -119,14 +119,14 @@ spec: app: sliceservice # same as above #release: prometheus # same as above endpoints: - - port: metrics # named port in target app - scheme: http - path: /metrics # path to scrape - interval: 5s # scrape interval + - port: metrics # named port in target app + scheme: http + path: /metrics # path to scrape + interval: 5s # scrape interval namespaceSelector: any: false matchNames: - - tfs # namespace where the app is running + - tfs # namespace where the app is running --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor @@ -136,9 +136,9 @@ metadata: labels: app: pathcompservice #release: prometheus - #release: prom # name of the release - # ( VERY IMPORTANT: You need to know the correct release name by viewing - # the servicemonitor of Prometheus itself: Without the correct name, + #release: prom # name of the release + # ( VERY IMPORTANT: You need to know the correct release name by viewing + # the servicemonitor of Prometheus itself: Without the correct name, # Prometheus cannot identify the metrics of the Flask app as the target.) spec: selector: @@ -148,14 +148,14 @@ spec: app: pathcompservice # same as above #release: prometheus # same as above endpoints: - - port: metrics # named port in target app - scheme: http - path: /metrics # path to scrape - interval: 5s # scrape interval + - port: metrics # named port in target app + scheme: http + path: /metrics # path to scrape + interval: 5s # scrape interval namespaceSelector: any: false matchNames: - - tfs # namespace where the app is running + - tfs # namespace where the app is running --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor @@ -165,9 +165,9 @@ metadata: labels: app: monitoringservice #release: prometheus - #release: prom # name of the release - # ( VERY IMPORTANT: You need to know the correct release name by viewing - # the servicemonitor of Prometheus itself: Without the correct name, + #release: prom # name of the release + # ( VERY IMPORTANT: You need to know the correct release name by viewing + # the servicemonitor of Prometheus itself: Without the correct name, # Prometheus cannot identify the metrics of the Flask app as the target.) spec: selector: @@ -177,14 +177,14 @@ spec: app: monitoringservice # same as above #release: prometheus # same as above endpoints: - - port: metrics # named port in target app - scheme: http - path: /metrics # path to scrape - interval: 5s # scrape interval + - port: metrics # named port in target app + scheme: http + path: /metrics # path to scrape + interval: 5s # scrape interval namespaceSelector: any: false matchNames: - - tfs # namespace where the app is running + - tfs # namespace where the app is running --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor @@ -194,9 +194,9 @@ metadata: labels: app: dltservice #release: prometheus - #release: prom # name of the release - # ( VERY IMPORTANT: You need to know the correct release name by viewing - # the servicemonitor of Prometheus itself: Without the correct name, + #release: prom # name of the release + # ( VERY IMPORTANT: You need to know the correct release name by viewing + # the servicemonitor of Prometheus itself: Without the correct name, # Prometheus cannot identify the metrics of the Flask app as the target.) spec: selector: @@ -206,14 +206,14 @@ spec: app: dltservice # same as above #release: prometheus # same as above endpoints: - - port: metrics # named port in target app - scheme: http - path: /metrics # path to scrape - interval: 5s # scrape interval + - port: metrics # named port in target app + scheme: http + path: /metrics # path to scrape + interval: 5s # scrape interval namespaceSelector: any: false matchNames: - - tfs # namespace where the app is running + - tfs # namespace where the app is running --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor @@ -223,9 +223,9 @@ metadata: labels: app: interdomainservice #release: prometheus - #release: prom # name of the release - # ( VERY IMPORTANT: You need to know the correct release name by viewing - # the servicemonitor of Prometheus itself: Without the correct name, + #release: prom # name of the release + # ( VERY IMPORTANT: You need to know the correct release name by viewing + # the servicemonitor of Prometheus itself: Without the correct name, # Prometheus cannot identify the metrics of the Flask app as the target.) spec: selector: @@ -235,14 +235,14 @@ spec: app: interdomainservice # same as above #release: prometheus # same as above endpoints: - - port: metrics # named port in target app - scheme: http - path: /metrics # path to scrape - interval: 5s # scrape interval + - port: metrics # named port in target app + scheme: http + path: /metrics # path to scrape + interval: 5s # scrape interval namespaceSelector: any: false matchNames: - - tfs # namespace where the app is running + - tfs # namespace where the app is running --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor @@ -252,9 +252,9 @@ metadata: labels: app: policyservice #release: prometheus - #release: prom # name of the release - # ( VERY IMPORTANT: You need to know the correct release name by viewing - # the servicemonitor of Prometheus itself: Without the correct name, + #release: prom # name of the release + # ( VERY IMPORTANT: You need to know the correct release name by viewing + # the servicemonitor of Prometheus itself: Without the correct name, # Prometheus cannot identify the metrics of the Flask app as the target.) spec: selector: @@ -264,14 +264,14 @@ spec: app: policyservice # same as above #release: prometheus # same as above endpoints: - - port: metrics # named port in target app - scheme: http - path: /q/metrics # path to scrape - interval: 5s # scrape interval + - port: metrics # named port in target app + scheme: http + path: /q/metrics # path to scrape + interval: 5s # scrape interval namespaceSelector: any: false matchNames: - - tfs # namespace where the app is running + - tfs # namespace where the app is running --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor @@ -281,9 +281,9 @@ metadata: labels: app: ztpservice #release: prometheus - #release: prom # name of the release - # ( VERY IMPORTANT: You need to know the correct release name by viewing - # the servicemonitor of Prometheus itself: Without the correct name, + #release: prom # name of the release + # ( VERY IMPORTANT: You need to know the correct release name by viewing + # the servicemonitor of Prometheus itself: Without the correct name, # Prometheus cannot identify the metrics of the Flask app as the target.) spec: selector: @@ -293,14 +293,14 @@ spec: app: ztpservice # same as above #release: prometheus # same as above endpoints: - - port: metrics # named port in target app - scheme: http - path: /q/metrics # path to scrape - interval: 5s # scrape interval + - port: metrics # named port in target app + scheme: http + path: /q/metrics # path to scrape + interval: 5s # scrape interval namespaceSelector: any: false matchNames: - - tfs # namespace where the app is running + - tfs # namespace where the app is running --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor @@ -310,9 +310,9 @@ metadata: labels: app: nbiservice #release: prometheus - #release: prom # name of the release - # ( VERY IMPORTANT: You need to know the correct release name by viewing - # the servicemonitor of Prometheus itself: Without the correct name, + #release: prom # name of the release + # ( VERY IMPORTANT: You need to know the correct release name by viewing + # the servicemonitor of Prometheus itself: Without the correct name, # Prometheus cannot identify the metrics of the Flask app as the target.) spec: selector: @@ -322,14 +322,14 @@ spec: app: nbiservice # same as above #release: prometheus # same as above endpoints: - - port: metrics # named port in target app - scheme: http - path: /metrics # path to scrape - interval: 5s # scrape interval + - port: metrics # named port in target app + scheme: http + path: /metrics # path to scrape + interval: 5s # scrape interval namespaceSelector: any: false matchNames: - - tfs # namespace where the app is running + - tfs # namespace where the app is running --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor @@ -339,9 +339,9 @@ metadata: labels: app: load-generatorservice #release: prometheus - #release: prom # name of the release - # ( VERY IMPORTANT: You need to know the correct release name by viewing - # the servicemonitor of Prometheus itself: Without the correct name, + #release: prom # name of the release + # ( VERY IMPORTANT: You need to know the correct release name by viewing + # the servicemonitor of Prometheus itself: Without the correct name, # Prometheus cannot identify the metrics of the Flask app as the target.) spec: selector: @@ -351,14 +351,14 @@ spec: app: load-generatorservice # same as above #release: prometheus # same as above endpoints: - - port: metrics # named port in target app - scheme: http - path: /metrics # path to scrape - interval: 5s # scrape interval + - port: metrics # named port in target app + scheme: http + path: /metrics # path to scrape + interval: 5s # scrape interval namespaceSelector: any: false matchNames: - - tfs # namespace where the app is running + - tfs # namespace where the app is running --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor @@ -368,9 +368,9 @@ metadata: labels: app: dbscanservingservice #release: prometheus - #release: prom # name of the release - # ( VERY IMPORTANT: You need to know the correct release name by viewing - # the servicemonitor of Prometheus itself: Without the correct name, + #release: prom # name of the release + # ( VERY IMPORTANT: You need to know the correct release name by viewing + # the servicemonitor of Prometheus itself: Without the correct name, # Prometheus cannot identify the metrics of the Flask app as the target.) spec: selector: @@ -380,14 +380,14 @@ spec: app: dbscanservingservice # same as above #release: prometheus # same as above endpoints: - - port: metrics # named port in target app - scheme: http - path: /metrics # path to scrape - interval: 5s # scrape interval + - port: metrics # named port in target app + scheme: http + path: /metrics # path to scrape + interval: 5s # scrape interval namespaceSelector: any: false matchNames: - - tfs # namespace where the app is running + - tfs # namespace where the app is running --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor @@ -397,9 +397,9 @@ metadata: labels: app: opticalattackmitigatorservice #release: prometheus - #release: prom # name of the release - # ( VERY IMPORTANT: You need to know the correct release name by viewing - # the servicemonitor of Prometheus itself: Without the correct name, + #release: prom # name of the release + # ( VERY IMPORTANT: You need to know the correct release name by viewing + # the servicemonitor of Prometheus itself: Without the correct name, # Prometheus cannot identify the metrics of the Flask app as the target.) spec: selector: @@ -409,14 +409,14 @@ spec: app: opticalattackmitigatorservice # same as above #release: prometheus # same as above endpoints: - - port: metrics # named port in target app - scheme: http - path: /metrics # path to scrape - interval: 5s # scrape interval + - port: metrics # named port in target app + scheme: http + path: /metrics # path to scrape + interval: 5s # scrape interval namespaceSelector: any: false matchNames: - - tfs # namespace where the app is running + - tfs # namespace where the app is running --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor @@ -426,9 +426,9 @@ metadata: labels: app: opticalattackdetectorservice #release: prometheus - #release: prom # name of the release - # ( VERY IMPORTANT: You need to know the correct release name by viewing - # the servicemonitor of Prometheus itself: Without the correct name, + #release: prom # name of the release + # ( VERY IMPORTANT: You need to know the correct release name by viewing + # the servicemonitor of Prometheus itself: Without the correct name, # Prometheus cannot identify the metrics of the Flask app as the target.) spec: selector: @@ -438,14 +438,14 @@ spec: app: opticalattackdetectorservice # same as above #release: prometheus # same as above endpoints: - - port: metrics # named port in target app - scheme: http - path: /metrics # path to scrape - interval: 5s # scrape interval + - port: metrics # named port in target app + scheme: http + path: /metrics # path to scrape + interval: 5s # scrape interval namespaceSelector: any: false matchNames: - - tfs # namespace where the app is running + - tfs # namespace where the app is running --- apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor @@ -455,9 +455,9 @@ metadata: labels: app: opticalattackmanagerservice #release: prometheus - #release: prom # name of the release - # ( VERY IMPORTANT: You need to know the correct release name by viewing - # the servicemonitor of Prometheus itself: Without the correct name, + #release: prom # name of the release + # ( VERY IMPORTANT: You need to know the correct release name by viewing + # the servicemonitor of Prometheus itself: Without the correct name, # Prometheus cannot identify the metrics of the Flask app as the target.) spec: selector: @@ -467,11 +467,11 @@ spec: app: opticalattackmanagerservice # same as above #release: prometheus # same as above endpoints: - - port: metrics # named port in target app - scheme: http - path: /metrics # path to scrape - interval: 5s # scrape interval + - port: metrics # named port in target app + scheme: http + path: /metrics # path to scrape + interval: 5s # scrape interval namespaceSelector: any: false matchNames: - - tfs # namespace where the app is running + - tfs # namespace where the app is running diff --git a/manifests/serviceservice.yaml b/manifests/serviceservice.yaml index 7d7bdaa4e..2fb7ebb87 100644 --- a/manifests/serviceservice.yaml +++ b/manifests/serviceservice.yaml @@ -28,28 +28,28 @@ spec: spec: terminationGracePeriodSeconds: 5 containers: - - name: server - image: labs.etsi.org:5050/tfs/controller/service:latest - imagePullPolicy: Always - ports: - - containerPort: 3030 - - containerPort: 9192 - env: - - name: LOG_LEVEL - value: "INFO" - readinessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:3030"] - livenessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:3030"] - resources: - requests: - cpu: 250m - memory: 128Mi - limits: - cpu: 1000m - memory: 1024Mi + - name: server + image: labs.etsi.org:5050/tfs/controller/service:latest + imagePullPolicy: Always + ports: + - containerPort: 3030 + - containerPort: 9192 + env: + - name: LOG_LEVEL + value: "INFO" + readinessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:3030"] + livenessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:3030"] + resources: + requests: + cpu: 250m + memory: 128Mi + limits: + cpu: 1000m + memory: 1024Mi --- apiVersion: v1 kind: Service @@ -62,14 +62,14 @@ spec: selector: app: serviceservice ports: - - name: grpc - protocol: TCP - port: 3030 - targetPort: 3030 - - name: metrics - protocol: TCP - port: 9192 - targetPort: 9192 + - name: grpc + protocol: TCP + port: 3030 + targetPort: 3030 + - name: metrics + protocol: TCP + port: 9192 + targetPort: 9192 --- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler @@ -83,12 +83,12 @@ spec: minReplicas: 1 maxReplicas: 20 metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 80 + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 80 #behavior: # scaleDown: # stabilizationWindowSeconds: 30 diff --git a/manifests/sliceservice.yaml b/manifests/sliceservice.yaml index e7e5c1604..0daa8e70f 100644 --- a/manifests/sliceservice.yaml +++ b/manifests/sliceservice.yaml @@ -28,33 +28,33 @@ spec: spec: terminationGracePeriodSeconds: 5 containers: - - name: server - image: labs.etsi.org:5050/tfs/controller/slice:latest - imagePullPolicy: Always - ports: - - containerPort: 4040 - - containerPort: 9192 - env: - - name: LOG_LEVEL - value: "INFO" - - name: SLICE_GROUPING - value: "DISABLE" - envFrom: - - secretRef: - name: qdb-data - readinessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:4040"] - livenessProbe: - exec: - command: ["/bin/grpc_health_probe", "-addr=:4040"] - resources: - requests: - cpu: 250m - memory: 128Mi - limits: - cpu: 1000m - memory: 1024Mi + - name: server + image: labs.etsi.org:5050/tfs/controller/slice:latest + imagePullPolicy: Always + ports: + - containerPort: 4040 + - containerPort: 9192 + env: + - name: LOG_LEVEL + value: "INFO" + - name: SLICE_GROUPING + value: "DISABLE" + envFrom: + - secretRef: + name: qdb-data + readinessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:4040"] + livenessProbe: + exec: + command: ["/bin/grpc_health_probe", "-addr=:4040"] + resources: + requests: + cpu: 250m + memory: 128Mi + limits: + cpu: 1000m + memory: 1024Mi --- apiVersion: v1 kind: Service @@ -67,14 +67,14 @@ spec: selector: app: sliceservice ports: - - name: grpc - protocol: TCP - port: 4040 - targetPort: 4040 - - name: metrics - protocol: TCP - port: 9192 - targetPort: 9192 + - name: grpc + protocol: TCP + port: 4040 + targetPort: 4040 + - name: metrics + protocol: TCP + port: 9192 + targetPort: 9192 --- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler @@ -88,12 +88,12 @@ spec: minReplicas: 1 maxReplicas: 20 metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 80 + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 80 #behavior: # scaleDown: # stabilizationWindowSeconds: 30 diff --git a/manifests/teservice.yaml b/manifests/teservice.yaml index 15f1619df..ec8f2e3d6 100644 --- a/manifests/teservice.yaml +++ b/manifests/teservice.yaml @@ -30,37 +30,37 @@ spec: terminationGracePeriodSeconds: 5 shareProcessNamespace: true containers: - - name: server - image: labs.etsi.org:5050/tfs/controller/te:latest - imagePullPolicy: Always - ports: - - containerPort: 10030 - env: - - name: ERLANG_LOGGER_LEVEL - value: "debug" - - name: ERLANG_COOKIE - value: "tfte-unsafe-cookie" - - name: ERLANG_NODE_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: ERLANG_NODE_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - readinessProbe: - exec: - command: ["/tfte/bin/tfte", "status"] - livenessProbe: - exec: - command: ["/tfte/bin/tfte", "status"] - resources: - requests: - cpu: 250m - memory: 512Mi - limits: - cpu: 700m - memory: 1024Mi + - name: server + image: labs.etsi.org:5050/tfs/controller/te:latest + imagePullPolicy: Always + ports: + - containerPort: 10030 + env: + - name: ERLANG_LOGGER_LEVEL + value: "debug" + - name: ERLANG_COOKIE + value: "tfte-unsafe-cookie" + - name: ERLANG_NODE_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: ERLANG_NODE_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + readinessProbe: + exec: + command: ["/tfte/bin/tfte", "status"] + livenessProbe: + exec: + command: ["/tfte/bin/tfte", "status"] + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 700m + memory: 1024Mi --- apiVersion: v1 kind: Service @@ -71,11 +71,11 @@ spec: selector: app: teservice ports: - - name: grpc - protocol: TCP - port: 10030 - targetPort: 10030 - - name: pcep - protocol: TCP - port: 4189 - targetPort: 4189 + - name: grpc + protocol: TCP + port: 10030 + targetPort: 10030 + - name: pcep + protocol: TCP + port: 4189 + targetPort: 4189 diff --git a/manifests/webuiservice.yaml b/manifests/webuiservice.yaml index 43caa9f04..bb2573c45 100644 --- a/manifests/webuiservice.yaml +++ b/manifests/webuiservice.yaml @@ -32,73 +32,73 @@ spec: supplementalGroups: - 0 containers: - - name: server - image: labs.etsi.org:5050/tfs/controller/webui:latest - imagePullPolicy: Always - ports: - - containerPort: 8004 - env: - - name: LOG_LEVEL - value: "INFO" - - name: WEBUISERVICE_SERVICE_BASEURL_HTTP - value: "/webui/" - readinessProbe: - httpGet: - path: /healthz/ready - port: 8004 - initialDelaySeconds: 5 - timeoutSeconds: 1 - livenessProbe: - httpGet: - path: /healthz/live - port: 8004 - initialDelaySeconds: 5 - timeoutSeconds: 1 - resources: - requests: - cpu: 50m - memory: 128Mi - limits: - cpu: 1000m - memory: 1024Mi - - name: grafana - image: grafana/grafana:8.5.22 - imagePullPolicy: IfNotPresent - ports: - - containerPort: 3000 - name: http-grafana - protocol: TCP - env: - - name: GF_SERVER_ROOT_URL - value: "http://0.0.0.0:3000/grafana/" - - name: GF_SERVER_SERVE_FROM_SUB_PATH - value: "true" - readinessProbe: - failureThreshold: 60 - httpGet: - #path: /robots.txt - path: /login - port: 3000 - scheme: HTTP - initialDelaySeconds: 1 - periodSeconds: 1 - successThreshold: 1 - timeoutSeconds: 2 - livenessProbe: - failureThreshold: 60 - initialDelaySeconds: 1 - periodSeconds: 1 - successThreshold: 1 - tcpSocket: - port: 3000 - timeoutSeconds: 1 - resources: - requests: - cpu: 250m - memory: 512Mi - limits: - cpu: 500m - memory: 1024Mi + - name: server + image: labs.etsi.org:5050/tfs/controller/webui:latest + imagePullPolicy: Always + ports: + - containerPort: 8004 + env: + - name: LOG_LEVEL + value: "INFO" + - name: WEBUISERVICE_SERVICE_BASEURL_HTTP + value: "/webui/" + readinessProbe: + httpGet: + path: /healthz/ready + port: 8004 + initialDelaySeconds: 5 + timeoutSeconds: 1 + livenessProbe: + httpGet: + path: /healthz/live + port: 8004 + initialDelaySeconds: 5 + timeoutSeconds: 1 + resources: + requests: + cpu: 50m + memory: 128Mi + limits: + cpu: 1000m + memory: 1024Mi + - name: grafana + image: grafana/grafana:8.5.22 + imagePullPolicy: IfNotPresent + ports: + - containerPort: 3000 + name: http-grafana + protocol: TCP + env: + - name: GF_SERVER_ROOT_URL + value: "http://0.0.0.0:3000/grafana/" + - name: GF_SERVER_SERVE_FROM_SUB_PATH + value: "true" + readinessProbe: + failureThreshold: 60 + httpGet: + #path: /robots.txt + path: /login + port: 3000 + scheme: HTTP + initialDelaySeconds: 1 + periodSeconds: 1 + successThreshold: 1 + timeoutSeconds: 2 + livenessProbe: + failureThreshold: 60 + initialDelaySeconds: 1 + periodSeconds: 1 + successThreshold: 1 + tcpSocket: + port: 3000 + timeoutSeconds: 1 + resources: + requests: + cpu: 250m + memory: 512Mi + limits: + cpu: 500m + memory: 1024Mi --- apiVersion: v1 kind: Service @@ -111,9 +111,9 @@ spec: selector: app: webuiservice ports: - - name: webui - port: 8004 - targetPort: 8004 - - name: grafana - port: 3000 - targetPort: 3000 + - name: webui + port: 8004 + targetPort: 8004 + - name: grafana + port: 3000 + targetPort: 3000 diff --git a/manifests/ztpservice.yaml b/manifests/ztpservice.yaml index e2be80cea..608bab125 100644 --- a/manifests/ztpservice.yaml +++ b/manifests/ztpservice.yaml @@ -104,22 +104,22 @@ spec: limits: cpu: 2000m memory: 2048Mi ---- -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: ztpservice-hpa -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: ztpservice - minReplicas: 1 - maxReplicas: 10 - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 80 +#--- +#apiVersion: autoscaling/v2 +#kind: HorizontalPodAutoscaler +#metadata: +# name: ztpservice-hpa +#spec: +# scaleTargetRef: +# apiVersion: apps/v1 +# kind: Deployment +# name: ztpservice +# minReplicas: 1 +# maxReplicas: 10 +# metrics: +# - type: Resource +# resource: +# name: cpu +# target: +# type: Utilization +# averageUtilization: 80 diff --git a/my_deploy.sh b/my_deploy.sh index 0fcb51f90..9e4447349 100755 --- a/my_deploy.sh +++ b/my_deploy.sh @@ -20,11 +20,17 @@ export TFS_REGISTRY_IMAGES="http://localhost:32000/tfs/" # Set the list of components, separated by spaces, you want to build images for, and deploy. -export TFS_COMPONENTS="context device pathcomp service slice nbi webui load_generator" +export TFS_COMPONENTS="context device pathcomp opticalcontroller service slice nbi webui " # Uncomment to activate Monitoring #export TFS_COMPONENTS="${TFS_COMPONENTS} monitoring" +# Uncomment to activate BGP-LS Speaker +#export TFS_COMPONENTS="${TFS_COMPONENTS} bgpls_speaker" + +# Uncomment to activate Optical Controller +#export TFS_COMPONENTS="${TFS_COMPONENTS} opticalcontroller" + # Uncomment to activate ZTP #export TFS_COMPONENTS="${TFS_COMPONENTS} ztp" diff --git a/ofc24 b/ofc24 new file mode 100644 index 000000000..baae92c8e --- /dev/null +++ b/ofc24 @@ -0,0 +1 @@ +src/tests/ofc24/ \ No newline at end of file diff --git a/proto/bgpls.proto b/proto/bgpls.proto new file mode 100644 index 000000000..9b6f1efab --- /dev/null +++ b/proto/bgpls.proto @@ -0,0 +1,70 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; +package bgpls; + +import "context.proto"; + +service BgplsService { + rpc ListDiscoveredDevices (context.Empty ) returns (DiscoveredDeviceList) {} + rpc ListDiscoveredLinks (context.Empty ) returns (DiscoveredLinkList ) {} + rpc AddBgplsSpeaker (BgplsSpeaker ) returns (BgplsSpeakerId ) {} + rpc ListBgplsSpeakers (context.Empty ) returns (BgplsSpeakerList ) {} + rpc DisconnectFromSpeaker (BgplsSpeaker ) returns (context.Empty ) {} + rpc GetSpeakerInfoFromId (BgplsSpeakerId ) returns (BgplsSpeaker ) {} + rpc NotifyAddNodeToContext(NodeDescriptors) returns (context.Empty ) {} +} + +message DiscoveredDevice { + string nodeName = 1; + string ip = 2; + string igpID = 3; + string learntFrom = 4; +} + +message DiscoveredDeviceList { + repeated DiscoveredDevice discovereddevices = 1; +} + +message DiscoveredLinkList{ + repeated DiscoveredLink discoveredlinks = 1; +} + +message DiscoveredLink{ + NodeDescriptors local = 1; + NodeDescriptors remote = 2; + string learntFrom = 3; + string local_ipv4 = 4; + string remote_ipv4 = 5; +} + +message NodeDescriptors{ + string asNumber = 1; + string igp_id = 2; + string nodeName = 3; +} + +message BgplsSpeaker{ + string address = 1; + string port = 2; + string asNumber = 3; +} +message BgplsSpeakerId{ + uint32 id = 1; +} + +message BgplsSpeakerList{ + repeated BgplsSpeakerId speakers = 1; +} diff --git a/proto/context.proto b/proto/context.proto index d5022ac29..55c412119 100644 --- a/proto/context.proto +++ b/proto/context.proto @@ -74,6 +74,17 @@ service ContextService { rpc SetConnection (Connection ) returns ( ConnectionId ) {} rpc RemoveConnection (ConnectionId ) returns ( Empty ) {} rpc GetConnectionEvents(Empty ) returns (stream ConnectionEvent ) {} + + + // ------------------------------ Experimental ----------------------------- + rpc GetOpticalConfig (Empty ) returns (OpticalConfigList ) {} + rpc SetOpticalConfig (OpticalConfig ) returns (OpticalConfigId ) {} + rpc SelectOpticalConfig(OpticalConfigId) returns (OpticalConfig ) {} + rpc DeleteOpticalConfig(OpticalConfigId) returns (Empty ) {} + + rpc SetOpticalLink (OpticalLink ) returns (Empty ) {} + rpc GetOpticalLink (OpticalLinkId ) returns (OpticalLink ) {} + rpc GetFiber (FiberId ) returns (Fiber ) {} } // ----- Generic ------------------------------------------------------------------------------------------------------- @@ -203,6 +214,7 @@ enum DeviceDriverEnum { DEVICEDRIVER_GNMI_OPENCONFIG = 8; DEVICEDRIVER_FLEXSCALE = 9; DEVICEDRIVER_IETF_ACTN = 10; + DEVICEDRIVER_OC = 11; } enum DeviceOperationalStatusEnum { @@ -288,6 +300,7 @@ enum ServiceTypeEnum { SERVICETYPE_TAPI_CONNECTIVITY_SERVICE = 3; SERVICETYPE_TE = 4; SERVICETYPE_E2E = 5; + SERVICETYPE_OPTICAL_CONNECTIVITY = 6; } enum ServiceStatusEnum { @@ -612,3 +625,59 @@ message AuthenticationResult { ContextId context_id = 1; bool authenticated = 2; } + +// ---------------- Experimental ------------------------ +message OpticalConfigId { + string opticalconfig_uuid = 1; +} +message OpticalConfig { + OpticalConfigId opticalconfig_id = 1; + string config = 2; +} + +message OpticalConfigList { + repeated OpticalConfig opticalconfigs = 1; +} + +message OpticalConfigEvent { + Event event = 1; + OpticalConfigId opticalconfig_id = 2; +} + + +// ---- Optical Link ---- + +message OpticalLinkId { + Uuid optical_link_uuid = 1; +} + +message FiberId { + Uuid fiber_uuid = 1; +} + +message Fiber { + string ID = 10; + string src_port = 1; + string dst_port = 2; + string local_peer_port = 3; + string remote_peer_port = 4; + repeated int32 c_slots = 5; + repeated int32 l_slots = 6; + repeated int32 s_slots = 7; + float length = 8; + bool used = 9; + FiberId fiber_uuid = 11; + +} +message OpticalLinkDetails { + float length = 1; + string source = 2; + string target = 3; + repeated Fiber fibers = 4; +} + +message OpticalLink { + string name = 1; + OpticalLinkDetails details = 2; + OpticalLinkId optical_link_uuid = 3; +} diff --git a/proto/openconfig_device.proto b/proto/openconfig_device.proto new file mode 100644 index 000000000..913ac247e --- /dev/null +++ b/proto/openconfig_device.proto @@ -0,0 +1,23 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; +package openconfig_device; + +import "context.proto"; + +service OpenConfigService { + rpc AddOpenConfigDevice (context.OpticalConfig) returns (context.OpticalConfigId) {} + rpc ConfigureOpticalDevice(context.OpticalConfig) returns (context.Empty ) {} +} diff --git a/scripts/expose_ingress_grpc.sh b/scripts/expose_ingress_grpc.sh new file mode 100644 index 000000000..4fec2f219 --- /dev/null +++ b/scripts/expose_ingress_grpc.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +######################################################################################################################## +# Define your deployment settings here +######################################################################################################################## + +# If not already set, set the name of the Kubernetes namespace to deploy to. +export TFS_K8S_NAMESPACE=${TFS_K8S_NAMESPACE:-"tfs"} + +# If not already set, set the list of components you want to build images for, and deploy. +export TFS_COMPONENTS=${TFS_COMPONENTS:-"context device ztp policy service nbi monitoring dbscanserving opticalattackmitigator opticalcentralizedattackdetector l3_attackmitigator l3_centralizedattackdetector webui"} + +######################################################################################################################## +# Automated steps start here +######################################################################################################################## + +echo "Exposing GRPC ports for components..." +for COMPONENT in $TFS_COMPONENTS; do + echo "Processing '$COMPONENT' component..." + + SERVICE_GRPC_PORT=$(kubectl get service ${COMPONENT}service --namespace $TFS_K8S_NAMESPACE -o 'jsonpath={.spec.ports[?(@.name=="grpc")].port}') + echo " '$COMPONENT' service port: $SERVICE_GRPC_PORT" + if [ -z "${SERVICE_GRPC_PORT}" ]; then + printf "\n" + continue; + fi + + COMPONENT_OBJNAME=$(echo "${COMPONENT}" | sed "s/\_/-/") + PATCH='{"data": {"'${SERVICE_GRPC_PORT}'": "'$TFS_K8S_NAMESPACE'/'${COMPONENT_OBJNAME}service':'${SERVICE_GRPC_PORT}'"}}' + #echo "PATCH: ${PATCH}" + kubectl patch configmap nginx-ingress-tcp-microk8s-conf --namespace ingress --patch "${PATCH}" + + PORT_MAP='{"containerPort": '${SERVICE_GRPC_PORT}', "hostPort": '${SERVICE_GRPC_PORT}'}' + CONTAINER='{"name": "nginx-ingress-microk8s", "ports": ['${PORT_MAP}']}' + PATCH='{"spec": {"template": {"spec": {"containers": ['${CONTAINER}']}}}}' + #echo "PATCH: ${PATCH}" + kubectl patch daemonset nginx-ingress-microk8s-controller --namespace ingress --patch "${PATCH}" + + printf "\n" +done + +echo "Done!" diff --git a/scripts/run_tests_docker.sh b/scripts/run_tests_docker.sh new file mode 100644 index 000000000..23d920487 --- /dev/null +++ b/scripts/run_tests_docker.sh @@ -0,0 +1,88 @@ +#!/bin/bash +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +######################################################################################################################## +# Define your deployment settings here +######################################################################################################################## + +# Set the URL of your local Docker registry where the images will be uploaded to. Leave it blank if you do not want to +# use any Docker registry. +REGISTRY_IMAGE="" +#REGISTRY_IMAGE="http://my-container-registry.local/" + +# Set the list of components you want to build images for, and deploy. +COMPONENTS="context device ztp policy service nbi monitoring centralizedattackdetector" + +# Set the tag you want to use for your images. +IMAGE_TAG="tf-dev" + +# Constants +TMP_FOLDER="./tmp" + +TMP_LOGS_FOLDER="$TMP_FOLDER/logs" +mkdir -p $TMP_LOGS_FOLDER + +DOCKER_BUILD="docker build" +DOCKER_MAJOR_VERSION=$(docker --version | grep -o -E "Docker version [0-9]+\." | grep -o -E "[0-9]+" | cut -c 1-3) +if [[ $DOCKER_MAJOR_VERSION -ge 23 ]]; then + # If Docker version >= 23, build command was migrated to docker-buildx + # In Ubuntu, in practice, means to install package docker-buildx together with docker.io + # Check if docker-buildx plugin is installed + docker buildx version 1>/dev/null 2>/dev/null + if [[ $? -ne 0 ]]; then + echo "Docker buildx command is not installed. Check: https://docs.docker.com/build/architecture/#install-buildx" + echo "If you installed docker through APT package docker.io, consider installing also package docker-buildx" + exit 1; + fi + DOCKER_BUILD="docker buildx build" +fi + +for COMPONENT in $COMPONENTS; do + echo "Processing '$COMPONENT' component..." + IMAGE_NAME="$COMPONENT:$IMAGE_TAG" + IMAGE_URL="$REGISTRY_IMAGE/$IMAGE_NAME" + + echo " Building Docker image..." + BUILD_LOG="$TMP_LOGS_FOLDER/build_${COMPONENT}.log" + + if [ "$COMPONENT" == "ztp" ] || [ "$COMPONENT" == "policy" ]; then + $DOCKER_BUILD -t "$IMAGE_NAME" -f ./src/"$COMPONENT"/Dockerfile ./src/"$COMPONENT"/ > "$BUILD_LOG" + else + $DOCKER_BUILD -t "$IMAGE_NAME" -f ./src/"$COMPONENT"/Dockerfile ./src/ > "$BUILD_LOG" + fi + + if [ -n "$REGISTRY_IMAGE" ]; then + echo "Pushing Docker image to '$REGISTRY_IMAGE'..." + + TAG_LOG="$TMP_LOGS_FOLDER/tag_${COMPONENT}.log" + docker tag "$IMAGE_NAME" "$IMAGE_URL" > "$TAG_LOG" + + PUSH_LOG="$TMP_LOGS_FOLDER/push_${COMPONENT}.log" + docker push "$IMAGE_URL" > "$PUSH_LOG" + fi +done + +echo "Preparing for running the tests..." + +if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create -d bridge teraflowbridge; fi + +for COMPONENT in $COMPONENTS; do + IMAGE_NAME="$COMPONENT:$IMAGE_TAG" + echo " Running tests for $COMPONENT:" + docker run -it -d --name $COMPONENT $IMAGE_NAME --network=teraflowbridge + docker exec -it $COMPONENT bash -c "pytest --log-level=DEBUG --verbose $COMPONENT/tests/test_unitary.py" + docker stop $COMPONENT +done diff --git a/scripts/run_tests_locally-optical-attack-detector.sh b/scripts/run_tests_locally-optical-attack-detector.sh new file mode 100644 index 000000000..e34c62b56 --- /dev/null +++ b/scripts/run_tests_locally-optical-attack-detector.sh @@ -0,0 +1,102 @@ +#!/bin/bash +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +PROJECTDIR=`pwd` +RCFILE=$PROJECTDIR/coverage/.coveragerc +COVERAGEFILE=$PROJECTDIR/coverage/.coverage + +# Destroy old coverage file and configure the correct folder on the .coveragerc file +rm -f $COVERAGEFILE +cat $PROJECTDIR/coverage/.coveragerc.template | sed s+~/tfs-ctrl+$PROJECTDIR+g > $RCFILE + +echo +echo "Pre-test clean-up:" +echo "------------------" +docker rm -f redis opticalattackdetector dbscanserving +docker network rm tfs_br + +echo +echo "Pull Docker images:" +echo "-------------------" +docker pull redis:7.0-alpine + +echo +echo "Build optical attack detector:" +echo "------------------------------" +docker build -t "opticalattackdetector:latest" -f ./src/opticalattackdetector/Dockerfile . +docker images --filter="dangling=true" --quiet | xargs -r docker rmi + +echo +echo "Build dbscan serving:" +echo "---------------------" +docker build -t "dbscanserving:latest" -f ./src/dbscanserving/Dockerfile . +docker images --filter="dangling=true" --quiet | xargs -r docker rmi + +echo +echo "Create test environment:" +echo "------------------------" +export REDIS_PASSWORD=$(uuidgen) +docker network create -d bridge --subnet=172.254.254.0/24 --gateway=172.254.254.1 --ip-range=172.254.254.0/24 tfs_br + +docker run --name redis -d --network=tfs_br -p 16379:6379 --rm \ + --env REDIS_PASSWORD=${REDIS_PASSWORD} \ + redis:7.0-alpine redis-server --requirepass ${REDIS_PASSWORD} + +docker run --name dbscanserving -d --network=tfs_br -p 10008:10008 --rm \ + --env LOG_LEVEL=DEBUG \ + dbscanserving:latest "python -m dbscanserving.service" + +echo +echo "Waiting for initialization..." +echo "-----------------------------" +while ! docker logs redis 2>&1 | grep -q 'Ready to accept connections'; do sleep 1; done +docker logs redis +#while ! docker logs dbscanserving 2>&1 | grep -q 'Server is ready'; do sleep 1; done +docker logs dbscanserving +#sleep 10 +docker ps -a + +echo +echo "Run unitary tests and analyze code coverage:" +echo "--------------------------------------------" +export REDIS_ADDRESS=$(docker inspect redis --format "{{.NetworkSettings.Networks.tfs_br.IPAddress}}") +export DBSCANSERVING_ADDRESS=$(docker inspect dbscanserving --format "{{.NetworkSettings.Networks.tfs_br.IPAddress}}") +docker run --name opticalattackdetector -d --network=tfs_br -p 10006:10006 --rm \ + --env REDIS_PASSWORD=${REDIS_PASSWORD} \ + --env DBSCANSERVINGSERVICE_SERVICE_HOST=${DBSCANSERVING_ADDRESS} \ + --env CACHINGSERVICE_SERVICE_HOST=${REDIS_ADDRESS} \ + opticalattackdetector:latest + +sleep 5 +docker ps -a +docker logs opticalattackdetector +docker exec -i opticalattackdetector bash -c "coverage run -m pytest --log-level=DEBUG --verbose opticalattackdetector/tests/test_unitary.py" +docker logs redis +docker logs dbscanserving +docker logs opticalattackdetector + +echo +echo "Coverage report:" +echo "----------------" +docker exec -i opticalattackdetector bash -c "coverage report --include='opticalattackdetector/*' --sort cover --show-missing --skip-covered" + +echo +echo "Post-test clean-up:" +echo "-------------------" +docker rm -f redis opticalattackdetector dbscanserving +docker network rm tfs_br + +echo "Done!" diff --git a/scripts/show_logs_bgp.sh b/scripts/show_logs_bgp.sh new file mode 100644 index 000000000..29e8fa60c --- /dev/null +++ b/scripts/show_logs_bgp.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +######################################################################################################################## +# Define your deployment settings here +######################################################################################################################## + +# If not already set, set the name of the Kubernetes namespace to deploy to. +export TFS_K8S_NAMESPACE=${TFS_K8S_NAMESPACE:-"tfs"} + +######################################################################################################################## +# Automated steps start here +######################################################################################################################## + +kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/bgpls_speakerservice -c server diff --git a/scripts/show_logs_opticalcontroller.sh b/scripts/show_logs_opticalcontroller.sh new file mode 100644 index 000000000..17af5483c --- /dev/null +++ b/scripts/show_logs_opticalcontroller.sh @@ -0,0 +1,27 @@ +#!/bin/bash +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +######################################################################################################################## +# Define your deployment settings here +######################################################################################################################## + +# If not already set, set the name of the Kubernetes namespace to deploy to. +export TFS_K8S_NAMESPACE=${TFS_K8S_NAMESPACE:-"tfs"} + +######################################################################################################################## +# Automated steps start here +######################################################################################################################## + +kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/opticalcontrollerservice -c server diff --git a/scripts/start_webui_dev_mode.sh b/scripts/start_webui_dev_mode.sh new file mode 100644 index 000000000..fe2587c1a --- /dev/null +++ b/scripts/start_webui_dev_mode.sh @@ -0,0 +1,37 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# for development purposes only + +# K8S_NAMESPACE=${K8S_NAMESPACE:-'tf-dev'} + +# export CONTEXTSERVICE_SERVICE_HOST=`kubectl get service/contextservice -n ${K8S_NAMESPACE} -o jsonpath='{.spec.clusterIP}'` + +# echo Context IP: $CONTEXTSERVICE_SERVICE_HOST + +# export DEVICESERVICE_SERVICE_HOST=`kubectl get service/deviceservice -n ${K8S_NAMESPACE} -o jsonpath='{.spec.clusterIP}'` + +# echo Device IP: $DEVICESERVICE_SERVICE_HOST + +source tfs_runtime_env_vars.sh + +export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION='python' +export HOST="127.0.0.1" +export HOSTNAME="test" +export FLASK_ENV="development" +export LOG_LEVEL="DEBUG" + +# python3 -m webbrowser http://${HOST}:8004 + +python -m webui.service diff --git a/scripts/wait_context_nats.sh b/scripts/wait_context_nats.sh new file mode 100644 index 000000000..900595741 --- /dev/null +++ b/scripts/wait_context_nats.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +######################################################################################################################## +# Define your deployment settings here +######################################################################################################################## + +# If not already set, set the name of the Kubernetes namespace to deploy to. +export TFS_K8S_NAMESPACE=${TFS_K8S_NAMESPACE:-"tfs"} + + +######################################################################################################################## +# Automated steps start here +######################################################################################################################## + +while ! kubectl --namespace $TFS_K8S_NAMESPACE logs deployment/contextservice -c server 2>&1 | grep -q 'Subscriber is Ready? True'; do sleep 1; done diff --git a/src/bgpls_speaker/.gitlab-ci.yml b/src/bgpls_speaker/.gitlab-ci.yml new file mode 100644 index 000000000..50b5ebf69 --- /dev/null +++ b/src/bgpls_speaker/.gitlab-ci.yml @@ -0,0 +1,105 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Build, tag, and push the Docker image to the GitLab Docker registry +build bgpls_speaker: + variables: + IMAGE_NAME: 'bgpls_speaker' # name of the microservice + IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) + stage: build + before_script: + - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY + script: + - docker buildx build -t "$IMAGE_NAME:$IMAGE_TAG" -f ./src/$IMAGE_NAME/Dockerfile . + - docker tag "$IMAGE_NAME:$IMAGE_TAG" "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" + - docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" + after_script: + - docker images --filter="dangling=true" --quiet | xargs -r docker rmi + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)' + - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' + - changes: + - src/common/**/*.py + - proto/*.proto + - src/$IMAGE_NAME/**/*.{py,in,yml} + - src/$IMAGE_NAME/Dockerfile + - src/$IMAGE_NAME/tests/*.py + - manifests/${IMAGE_NAME}service.yaml + - .gitlab-ci.yml + +## Apply unit test to the component +#unit_test bgpls_speaker: +# variables: +# IMAGE_NAME: 'bgpls_speaker' # name of the microservice +# IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) +# stage: unit_test +# needs: +# - build bgpls_speaker +# before_script: +# - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY +# - if docker network list | grep teraflowbridge; then echo "teraflowbridge is already created"; else docker network create --driver=bridge teraflowbridge; fi +# - if docker container ls | grep $IMAGE_NAME; then docker rm -f $IMAGE_NAME; else echo "$IMAGE_NAME image is not in the system"; fi +# script: +# - docker pull "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG" +# - docker run --name $IMAGE_NAME -d -p 20030:20030 -v "$PWD/src/$IMAGE_NAME/tests:/opt/results" --network=teraflowbridge $CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG +# - sleep 5 +# - docker ps -a +# - docker logs $IMAGE_NAME +# - docker exec -i $IMAGE_NAME bash -c "coverage run -m pytest --log-level=INFO --verbose $IMAGE_NAME/tests/test_unitary.py --junitxml=/opt/results/${IMAGE_NAME}_report.xml" +# - docker exec -i $IMAGE_NAME bash -c "coverage report --include='${IMAGE_NAME}/*' --show-missing" +# coverage: '/TOTAL\s+\d+\s+\d+\s+(\d+%)/' +# after_script: +# - docker rm -f $IMAGE_NAME +# - docker network rm teraflowbridge +# rules: +# - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)' +# - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' +# - changes: +# - src/common/**/*.py +# - proto/*.proto +# - src/$IMAGE_NAME/**/*.{py,in,yml} +# - src/$IMAGE_NAME/Dockerfile +# - src/$IMAGE_NAME/tests/*.py +# - manifests/${IMAGE_NAME}service.yaml +# - .gitlab-ci.yml +# artifacts: +# when: always +# reports: +# junit: src/$IMAGE_NAME/tests/${IMAGE_NAME}_report.xml + +## Deployment of the service in Kubernetes Cluster +#deploy bgpls_speaker: +# variables: +# IMAGE_NAME: 'bgpls_speaker' # name of the microservice +# IMAGE_TAG: 'latest' # tag of the container image (production, development, etc) +# stage: deploy +# needs: +# - unit test bgpls_speaker +# # - integ_test execute +# script: +# - 'sed -i "s/$IMAGE_NAME:.*/$IMAGE_NAME:$IMAGE_TAG/" manifests/${IMAGE_NAME}service.yaml' +# - kubectl version +# - kubectl get all +# - kubectl apply -f "manifests/${IMAGE_NAME}service.yaml" +# - kubectl get all +# # environment: +# # name: test +# # url: https://example.com +# # kubernetes: +# # namespace: test +# rules: +# - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && ($CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "develop" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH)' +# when: manual +# - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == "develop"' +# when: manual diff --git a/src/bgpls_speaker/Config.py b/src/bgpls_speaker/Config.py new file mode 100644 index 000000000..38d04994f --- /dev/null +++ b/src/bgpls_speaker/Config.py @@ -0,0 +1,13 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/src/bgpls_speaker/Dockerfile b/src/bgpls_speaker/Dockerfile new file mode 100644 index 000000000..87463943a --- /dev/null +++ b/src/bgpls_speaker/Dockerfile @@ -0,0 +1,110 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# +# Maven install stage +# +# ---------------------------------------------- +# FROM alpine/git:latest AS repo + +# WORKDIR /usr/src/app +# RUN git clone https://github.com/telefonicaid/netphony-network-protocols.git . + +FROM maven:3.8.8-eclipse-temurin-17 AS build + +WORKDIR / +COPY src/bgpls_speaker/service/java/netphony-topology/ netphony-topology/ +COPY src/bgpls_speaker/service/java/netphony-topology/pom.xml netphony-topology/pom.xml + +WORKDIR /netphony-topology/ +RUN mvn clean compile -DskipTests -X +RUN mvn package assembly:single -P bgp-ls-speaker -DskipTests +WORKDIR /netphony-topology/target/ +# ENTRYPOINT [ "ls" ,"-a"] +# ------------------------------------------- +# jar created in /netphony-topology/target/bgp-ls-speaker-jar-with-dependencies.jar + +# +# Stage 2 +# + +FROM python:3.9-slim + + +# Install dependencies +RUN apt-get --yes --quiet --quiet update && \ + apt-get --yes --quiet --quiet install wget g++ && \ + rm -rf /var/lib/apt/lists/* + +# Set Python to show logs as they occur +ENV PYTHONUNBUFFERED=0 + +# Download the gRPC health probe +RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \ + wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \ + chmod +x /bin/grpc_health_probe + +# Get generic Python packages +RUN python3 -m pip install --upgrade pip +RUN python3 -m pip install --upgrade setuptools wheel +RUN python3 -m pip install --upgrade pip-tools + +# Install OpenJDK-11 +RUN apt-get update && \ + apt-get install -y openjdk-17-jre && \ + apt-get clean; + +# Get common Python packages +# Note: this step enables sharing the previous Docker build steps among all the Python components +WORKDIR /var/teraflow +COPY common_requirements.in common_requirements.in +RUN pip-compile --quiet --output-file=common_requirements.txt common_requirements.in +RUN python3 -m pip install -r common_requirements.txt + +# Add common files into working directory +WORKDIR /var/teraflow/common +COPY src/common/. ./ +RUN rm -rf proto + +# Create proto sub-folder, copy .proto files, and generate Python code +RUN mkdir -p /var/teraflow/common/proto +WORKDIR /var/teraflow/common/proto +RUN touch __init__.py +COPY proto/*.proto ./ +RUN python3 -m grpc_tools.protoc -I=. --python_out=. --grpc_python_out=. *.proto +RUN rm *.proto +RUN find . -type f -exec sed -i -E 's/(import\ .*)_pb2/from . \1_pb2/g' {} \; + +# Create component sub-folders, get specific Python packages +RUN mkdir -p /var/teraflow/bgpls_speaker +WORKDIR /var/teraflow/bgpls_speaker +COPY src/bgpls_speaker/requirements.in requirements.in +RUN pip-compile --quiet --output-file=requirements.txt requirements.in +RUN python3 -m pip install -r requirements.txt + +# Java module necessary config files +WORKDIR /var/teraflow/bgpls_speaker +RUN mkdir -p /java +COPY src/bgpls_speaker/service/java/* /java/ +COPY --from=build /netphony-topology/target/bgp-ls-speaker-jar-with-dependencies.jar /var/teraflow/bgpls_speaker/service/java/bgp_ls.jar + +# Add component files into working directory +WORKDIR /var/teraflow +COPY src/context/__init__.py context/__init__.py +COPY src/context/client/. context/client/ +COPY src/bgpls_speaker/. bgpls_speaker/ + +# Start the service +ENTRYPOINT ["python", "-m", "bgpls_speaker.service"] +# ENTRYPOINT [ "ls","-R" ] \ No newline at end of file diff --git a/src/bgpls_speaker/__init__.py b/src/bgpls_speaker/__init__.py new file mode 100644 index 000000000..38d04994f --- /dev/null +++ b/src/bgpls_speaker/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/src/bgpls_speaker/client/BgplsClient.py b/src/bgpls_speaker/client/BgplsClient.py new file mode 100644 index 000000000..dc8ecf4ec --- /dev/null +++ b/src/bgpls_speaker/client/BgplsClient.py @@ -0,0 +1,91 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import grpc, logging +from common.Constants import ServiceNameEnum +from common.Settings import get_service_host, get_service_port_grpc +from common.proto.context_pb2 import Empty, Service, ServiceId +from common.proto.service_pb2_grpc import ServiceServiceStub +from common.proto.bgpls_pb2_grpc import BgplsServiceStub +from common.proto.bgpls_pb2 import BgplsSpeaker, DiscoveredDeviceList,DiscoveredLinkList,BgplsSpeakerId, NodeDescriptors +from common.tools.client.RetryDecorator import retry, delay_exponential +from common.tools.grpc.Tools import grpc_message_to_json_string + +LOGGER = logging.getLogger(__name__) +MAX_RETRIES = 15 +DELAY_FUNCTION = delay_exponential(initial=0.01, increment=2.0, maximum=5.0) +RETRY_DECORATOR = retry(max_retries=MAX_RETRIES, delay_function=DELAY_FUNCTION, prepare_method_name='connect') + +class BgplsClient: + def __init__(self, host=None, port=None): + if not host: host = get_service_host(ServiceNameEnum.BGPLS) + if not port: port = get_service_port_grpc(ServiceNameEnum.BGPLS) + self.endpoint = '{:s}:{:s}'.format(str(host), str(port)) + LOGGER.info('Creating channel to {:s}...'.format(str(self.endpoint))) + self.channel = None + self.stub = None + self.connect() + LOGGER.info('Channel created') + + def connect(self): + self.channel = grpc.insecure_channel(self.endpoint) + self.stub = BgplsServiceStub(self.channel) + + def close(self): + if self.channel is not None: self.channel.close() + self.channel = None + self.stub = None + + @RETRY_DECORATOR + def ListDiscoveredDevices(self, request: Empty) -> DiscoveredDeviceList: + LOGGER.info('ListDiscoveredDevices request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.ListDiscoveredDevices(request) + LOGGER.info('ListDiscoveredDevices result: {:s}'.format(grpc_message_to_json_string(response))) + return response + @RETRY_DECORATOR + def ListDiscoveredLinks(self, request: Empty) -> DiscoveredLinkList: + LOGGER.info('ListDiscoveredDevices request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.ListDiscoveredLinks(request) + LOGGER.info('ListDiscoveredDevices result: {:s}'.format(grpc_message_to_json_string(response))) + return response + @RETRY_DECORATOR + def AddBgplsSpeaker(self, request: BgplsSpeaker) -> str: + LOGGER.info('AddBgplsSpeaker request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.AddBgplsSpeaker(request) + LOGGER.info('AddBgplsSpeaker result: {:s}'.format(grpc_message_to_json_string(response))) + return response + @RETRY_DECORATOR + def ListBgplsSpeakers(self, request: Empty) -> BgplsSpeakerId: + LOGGER.info('ListBgplsSpeakers request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.ListBgplsSpeakers(request) + LOGGER.info('ListBgplsSpeakers result: {:s}'.format(grpc_message_to_json_string(response))) + return response + @RETRY_DECORATOR + def DisconnectFromSpeaker(self, request: BgplsSpeaker) -> bool: + LOGGER.info('DisconnectFromSpeaker request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.DisconnectFromSpeaker(request) + LOGGER.info('DisconnectFromSpeaker result: {:s}'.format(grpc_message_to_json_string(response))) + return response + @RETRY_DECORATOR + def GetSpeakerInfoFromId(self, request: BgplsSpeakerId) -> BgplsSpeaker: + LOGGER.info('GetSpeakerInfoFromId request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.GetSpeakerInfoFromId(request) + LOGGER.info('GetSpeakerInfoFromId result: {:s}'.format(grpc_message_to_json_string(response))) + return response + @RETRY_DECORATOR + def NotifyAddNodeToContext(self, request: NodeDescriptors) -> str: + LOGGER.info('NotifyAddNodeToContext request: {:s}'.format(grpc_message_to_json_string(request))) + response = self.stub.NotifyAddNodeToContext(request) + LOGGER.info('NotifyAddNodeToContext result: {:s}'.format(grpc_message_to_json_string(response))) + return response diff --git a/src/bgpls_speaker/client/__init__.py b/src/bgpls_speaker/client/__init__.py new file mode 100644 index 000000000..38d04994f --- /dev/null +++ b/src/bgpls_speaker/client/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/src/bgpls_speaker/quick_deploy.sh b/src/bgpls_speaker/quick_deploy.sh new file mode 100644 index 000000000..7276f3287 --- /dev/null +++ b/src/bgpls_speaker/quick_deploy.sh @@ -0,0 +1,438 @@ +#!/bin/bash +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +######################################################################################################################## +# Read deployment settings +######################################################################################################################## + + +# ----- TeraFlowSDN ------------------------------------------------------------ + +# If not already set, set the URL of the Docker registry where the images will be uploaded to. +# By default, assume internal MicroK8s registry is used. +export TFS_REGISTRY_IMAGES=${TFS_REGISTRY_IMAGES:-"http://localhost:32000/tfs/"} + +# If not already set, set the list of components, separated by spaces, you want to build images for, and deploy. +# By default, only basic components are deployed +export TFS_COMPONENTS=${TFS_COMPONENTS:-"context device pathcomp service slice nbi webui load_generator bgpls_speaker"} + +# If not already set, set the tag you want to use for your images. +export TFS_IMAGE_TAG=${TFS_IMAGE_TAG:-"dev"} + +# If not already set, set the name of the Kubernetes namespace to deploy TFS to. +export TFS_K8S_NAMESPACE=${TFS_K8S_NAMESPACE:-"tfs"} + +# If not already set, set additional manifest files to be applied after the deployment +export TFS_EXTRA_MANIFESTS=${TFS_EXTRA_MANIFESTS:-""} + +# If not already set, set the new Grafana admin password +export TFS_GRAFANA_PASSWORD=${TFS_GRAFANA_PASSWORD:-"admin123+"} + +# If not already set, disable skip-build flag to rebuild the Docker images. +# If TFS_SKIP_BUILD is "YES", the containers are not rebuilt-retagged-repushed and existing ones are used. +export TFS_SKIP_BUILD=${TFS_SKIP_BUILD:-"YES"} + +# If TFS_SKIP_BUILD is "YES", select the containers to be build +# Any other container will use previous docker images +export TFS_QUICK_COMPONENTS="bgpls_speaker" + +# ----- CockroachDB ------------------------------------------------------------ + +# If not already set, set the namespace where CockroackDB will be deployed. +export CRDB_NAMESPACE=${CRDB_NAMESPACE:-"crdb"} + +# If not already set, set the database username to be used by Context. +export CRDB_USERNAME=${CRDB_USERNAME:-"tfs"} + +# If not already set, set the database user's password to be used by Context. +export CRDB_PASSWORD=${CRDB_PASSWORD:-"tfs123"} + +# If not already set, set the database name to be used by Context. +export CRDB_DATABASE=${CRDB_DATABASE:-"tfs"} + + +# ----- NATS ------------------------------------------------------------------- + +# If not already set, set the namespace where NATS will be deployed. +export NATS_NAMESPACE=${NATS_NAMESPACE:-"nats"} + + +# ----- QuestDB ---------------------------------------------------------------- + +# If not already set, set the namespace where QuestDB will be deployed. +export QDB_NAMESPACE=${QDB_NAMESPACE:-"qdb"} + +# If not already set, set the database username to be used for QuestDB. +export QDB_USERNAME=${QDB_USERNAME:-"admin"} + +# If not already set, set the database user's password to be used for QuestDB. +export QDB_PASSWORD=${QDB_PASSWORD:-"quest"} + +# If not already set, set the table name to be used by Monitoring for KPIs. +export QDB_TABLE_MONITORING_KPIS=${QDB_TABLE_MONITORING_KPIS:-"tfs_monitoring_kpis"} + +# If not already set, set the table name to be used by Slice for plotting groups. +export QDB_TABLE_SLICE_GROUPS=${QDB_TABLE_SLICE_GROUPS:-"tfs_slice_groups"} + + +######################################################################################################################## +# Automated steps start here +######################################################################################################################## + +# Constants +GITLAB_REPO_URL="labs.etsi.org:5050/tfs/controller" +TMP_FOLDER="./tmp" + +# Create a tmp folder for files modified during the deployment +TMP_MANIFESTS_FOLDER="$TMP_FOLDER/manifests" +mkdir -p $TMP_MANIFESTS_FOLDER +TMP_LOGS_FOLDER="$TMP_FOLDER/logs" +mkdir -p $TMP_LOGS_FOLDER + +echo "Deleting and Creating a new namespace..." +kubectl delete namespace $TFS_K8S_NAMESPACE --ignore-not-found +kubectl create namespace $TFS_K8S_NAMESPACE +printf "\n" + +echo "Create secret with CockroachDB data" +CRDB_SQL_PORT=$(kubectl --namespace ${CRDB_NAMESPACE} get service cockroachdb-public -o 'jsonpath={.spec.ports[?(@.name=="sql")].port}') +kubectl create secret generic crdb-data --namespace ${TFS_K8S_NAMESPACE} --type='Opaque' \ + --from-literal=CRDB_NAMESPACE=${CRDB_NAMESPACE} \ + --from-literal=CRDB_SQL_PORT=${CRDB_SQL_PORT} \ + --from-literal=CRDB_DATABASE=${CRDB_DATABASE} \ + --from-literal=CRDB_USERNAME=${CRDB_USERNAME} \ + --from-literal=CRDB_PASSWORD=${CRDB_PASSWORD} \ + --from-literal=CRDB_SSLMODE=require +printf "\n" + +echo "Create secret with NATS data" +NATS_CLIENT_PORT=$(kubectl --namespace ${NATS_NAMESPACE} get service nats -o 'jsonpath={.spec.ports[?(@.name=="client")].port}') +kubectl create secret generic nats-data --namespace ${TFS_K8S_NAMESPACE} --type='Opaque' \ + --from-literal=NATS_NAMESPACE=${NATS_NAMESPACE} \ + --from-literal=NATS_CLIENT_PORT=${NATS_CLIENT_PORT} +printf "\n" + +echo "Create secret with QuestDB data" +QDB_HTTP_PORT=$(kubectl --namespace ${QDB_NAMESPACE} get service questdb-public -o 'jsonpath={.spec.ports[?(@.name=="http")].port}') +QDB_ILP_PORT=$(kubectl --namespace ${QDB_NAMESPACE} get service questdb-public -o 'jsonpath={.spec.ports[?(@.name=="ilp")].port}') +QDB_SQL_PORT=$(kubectl --namespace ${QDB_NAMESPACE} get service questdb-public -o 'jsonpath={.spec.ports[?(@.name=="sql")].port}') +METRICSDB_HOSTNAME="questdb-public.${QDB_NAMESPACE}.svc.cluster.local" +kubectl create secret generic qdb-data --namespace ${TFS_K8S_NAMESPACE} --type='Opaque' \ + --from-literal=QDB_NAMESPACE=${QDB_NAMESPACE} \ + --from-literal=METRICSDB_HOSTNAME=${METRICSDB_HOSTNAME} \ + --from-literal=METRICSDB_REST_PORT=${QDB_HTTP_PORT} \ + --from-literal=METRICSDB_ILP_PORT=${QDB_ILP_PORT} \ + --from-literal=METRICSDB_SQL_PORT=${QDB_SQL_PORT} \ + --from-literal=METRICSDB_TABLE_MONITORING_KPIS=${QDB_TABLE_MONITORING_KPIS} \ + --from-literal=METRICSDB_TABLE_SLICE_GROUPS=${QDB_TABLE_SLICE_GROUPS} \ + --from-literal=METRICSDB_USERNAME=${QDB_USERNAME} \ + --from-literal=METRICSDB_PASSWORD=${QDB_PASSWORD} +printf "\n" + +echo "Deploying components and collecting environment variables..." +ENV_VARS_SCRIPT=tfs_runtime_env_vars.sh +echo "# Environment variables for TeraFlowSDN deployment" > $ENV_VARS_SCRIPT +PYTHONPATH=$(pwd)/src +echo "export PYTHONPATH=${PYTHONPATH}" >> $ENV_VARS_SCRIPT + +for COMPONENT in $TFS_COMPONENTS; do + echo "Processing '$COMPONENT' component..." + + if [ "$TFS_SKIP_BUILD" != "YES" ]; then + echo " Building Docker image..." + BUILD_LOG="$TMP_LOGS_FOLDER/build_${COMPONENT}.log" + + if [ "$COMPONENT" == "automation" ] || [ "$COMPONENT" == "policy" ]; then + docker build -t "$COMPONENT:$TFS_IMAGE_TAG" -f ./src/"$COMPONENT"/Dockerfile ./src/"$COMPONENT"/ > "$BUILD_LOG" + elif [ "$COMPONENT" == "pathcomp" ]; then + BUILD_LOG="$TMP_LOGS_FOLDER/build_${COMPONENT}-frontend.log" + docker build -t "$COMPONENT-frontend:$TFS_IMAGE_TAG" -f ./src/"$COMPONENT"/frontend/Dockerfile . > "$BUILD_LOG" + + BUILD_LOG="$TMP_LOGS_FOLDER/build_${COMPONENT}-backend.log" + docker build -t "$COMPONENT-backend:$TFS_IMAGE_TAG" -f ./src/"$COMPONENT"/backend/Dockerfile . > "$BUILD_LOG" + # next command is redundant, but helpful to keep cache updated between rebuilds + IMAGE_NAME="$COMPONENT-backend:$TFS_IMAGE_TAG-builder" + docker build -t "$IMAGE_NAME" --target builder -f ./src/"$COMPONENT"/backend/Dockerfile . >> "$BUILD_LOG" + elif [ "$COMPONENT" == "dlt" ]; then + BUILD_LOG="$TMP_LOGS_FOLDER/build_${COMPONENT}-connector.log" + docker build -t "$COMPONENT-connector:$TFS_IMAGE_TAG" -f ./src/"$COMPONENT"/connector/Dockerfile . > "$BUILD_LOG" + + BUILD_LOG="$TMP_LOGS_FOLDER/build_${COMPONENT}-gateway.log" + docker build -t "$COMPONENT-gateway:$TFS_IMAGE_TAG" -f ./src/"$COMPONENT"/gateway/Dockerfile . > "$BUILD_LOG" + else + docker build -t "$COMPONENT:$TFS_IMAGE_TAG" -f ./src/"$COMPONENT"/Dockerfile . > "$BUILD_LOG" + fi + + echo " Pushing Docker image to '$TFS_REGISTRY_IMAGES'..." + + if [ "$COMPONENT" == "pathcomp" ]; then + IMAGE_URL=$(echo "$TFS_REGISTRY_IMAGES/$COMPONENT-frontend:$TFS_IMAGE_TAG" | sed 's,//,/,g' | sed 's,http:/,,g') + + TAG_LOG="$TMP_LOGS_FOLDER/tag_${COMPONENT}-frontend.log" + docker tag "$COMPONENT-frontend:$TFS_IMAGE_TAG" "$IMAGE_URL" > "$TAG_LOG" + + PUSH_LOG="$TMP_LOGS_FOLDER/push_${COMPONENT}-frontend.log" + docker push "$IMAGE_URL" > "$PUSH_LOG" + + IMAGE_URL=$(echo "$TFS_REGISTRY_IMAGES/$COMPONENT-backend:$TFS_IMAGE_TAG" | sed 's,//,/,g' | sed 's,http:/,,g') + + TAG_LOG="$TMP_LOGS_FOLDER/tag_${COMPONENT}-backend.log" + docker tag "$COMPONENT-backend:$TFS_IMAGE_TAG" "$IMAGE_URL" > "$TAG_LOG" + + PUSH_LOG="$TMP_LOGS_FOLDER/push_${COMPONENT}-backend.log" + docker push "$IMAGE_URL" > "$PUSH_LOG" + elif [ "$COMPONENT" == "dlt" ]; then + IMAGE_URL=$(echo "$TFS_REGISTRY_IMAGES/$COMPONENT-connector:$TFS_IMAGE_TAG" | sed 's,//,/,g' | sed 's,http:/,,g') + + TAG_LOG="$TMP_LOGS_FOLDER/tag_${COMPONENT}-connector.log" + docker tag "$COMPONENT-connector:$TFS_IMAGE_TAG" "$IMAGE_URL" > "$TAG_LOG" + + PUSH_LOG="$TMP_LOGS_FOLDER/push_${COMPONENT}-connector.log" + docker push "$IMAGE_URL" > "$PUSH_LOG" + + IMAGE_URL=$(echo "$TFS_REGISTRY_IMAGES/$COMPONENT-gateway:$TFS_IMAGE_TAG" | sed 's,//,/,g' | sed 's,http:/,,g') + + TAG_LOG="$TMP_LOGS_FOLDER/tag_${COMPONENT}-gateway.log" + docker tag "$COMPONENT-gateway:$TFS_IMAGE_TAG" "$IMAGE_URL" > "$TAG_LOG" + + PUSH_LOG="$TMP_LOGS_FOLDER/push_${COMPONENT}-gateway.log" + docker push "$IMAGE_URL" > "$PUSH_LOG" + else + IMAGE_URL=$(echo "$TFS_REGISTRY_IMAGES/$COMPONENT:$TFS_IMAGE_TAG" | sed 's,//,/,g' | sed 's,http:/,,g') + + TAG_LOG="$TMP_LOGS_FOLDER/tag_${COMPONENT}.log" + docker tag "$COMPONENT:$TFS_IMAGE_TAG" "$IMAGE_URL" > "$TAG_LOG" + + PUSH_LOG="$TMP_LOGS_FOLDER/push_${COMPONENT}.log" + docker push "$IMAGE_URL" > "$PUSH_LOG" + fi + else + for QUICK_COMPONENT in $TFS_QUICK_COMPONENTS; do + if [ "$COMPONENT" == "$QUICK_COMPONENT" ]; then + + echo " Building Docker image..." + BUILD_LOG="$TMP_LOGS_FOLDER/build_${QUICK_COMPONENT}.log" + + docker build -t "$QUICK_COMPONENT:$TFS_IMAGE_TAG" -f ./src/"$QUICK_COMPONENT"/Dockerfile . > "$BUILD_LOG" + echo " Pushing Docker image to '$TFS_REGISTRY_IMAGES'..." + + + + IMAGE_URL=$(echo "$TFS_REGISTRY_IMAGES/$QUICK_COMPONENT:$TFS_IMAGE_TAG" | sed 's,//,/,g' | sed 's,http:/,,g') + + TAG_LOG="$TMP_LOGS_FOLDER/tag_${QUICK_COMPONENT}.log" + docker tag "$QUICK_COMPONENT:$TFS_IMAGE_TAG" "$IMAGE_URL" > "$TAG_LOG" + + PUSH_LOG="$TMP_LOGS_FOLDER/push_${QUICK_COMPONENT}.log" + docker push "$IMAGE_URL" > "$PUSH_LOG" + fi + done + fi + + echo " Adapting '$COMPONENT' manifest file..." + MANIFEST="$TMP_MANIFESTS_FOLDER/${COMPONENT}service.yaml" + cp ./manifests/"${COMPONENT}"service.yaml "$MANIFEST" + + if [ "$COMPONENT" == "pathcomp" ]; then + IMAGE_URL=$(echo "$TFS_REGISTRY_IMAGES/$COMPONENT-frontend:$TFS_IMAGE_TAG" | sed 's,//,/,g' | sed 's,http:/,,g') + VERSION=$(grep -i "${GITLAB_REPO_URL}/${COMPONENT}-frontend:" "$MANIFEST" | cut -d ":" -f4) + sed -E -i "s#image: $GITLAB_REPO_URL/$COMPONENT-frontend:${VERSION}#image: $IMAGE_URL#g" "$MANIFEST" + + IMAGE_URL=$(echo "$TFS_REGISTRY_IMAGES/$COMPONENT-backend:$TFS_IMAGE_TAG" | sed 's,//,/,g' | sed 's,http:/,,g') + VERSION=$(grep -i "${GITLAB_REPO_URL}/${COMPONENT}-backend:" "$MANIFEST" | cut -d ":" -f4) + sed -E -i "s#image: $GITLAB_REPO_URL/$COMPONENT-backend:${VERSION}#image: $IMAGE_URL#g" "$MANIFEST" + elif [ "$COMPONENT" == "dlt" ]; then + IMAGE_URL=$(echo "$TFS_REGISTRY_IMAGES/$COMPONENT-connector:$TFS_IMAGE_TAG" | sed 's,//,/,g' | sed 's,http:/,,g') + VERSION=$(grep -i "${GITLAB_REPO_URL}/${COMPONENT}-connector:" "$MANIFEST" | cut -d ":" -f4) + sed -E -i "s#image: $GITLAB_REPO_URL/$COMPONENT-connector:${VERSION}#image: $IMAGE_URL#g" "$MANIFEST" + + IMAGE_URL=$(echo "$TFS_REGISTRY_IMAGES/$COMPONENT-gateway:$TFS_IMAGE_TAG" | sed 's,//,/,g' | sed 's,http:/,,g') + VERSION=$(grep -i "${GITLAB_REPO_URL}/${COMPONENT}-gateway:" "$MANIFEST" | cut -d ":" -f4) + sed -E -i "s#image: $GITLAB_REPO_URL/$COMPONENT-gateway:${VERSION}#image: $IMAGE_URL#g" "$MANIFEST" + else + IMAGE_URL=$(echo "$TFS_REGISTRY_IMAGES/$COMPONENT:$TFS_IMAGE_TAG" | sed 's,//,/,g' | sed 's,http:/,,g') + VERSION=$(grep -i "${GITLAB_REPO_URL}/${COMPONENT}:" "$MANIFEST" | cut -d ":" -f4) + sed -E -i "s#image: $GITLAB_REPO_URL/$COMPONENT:${VERSION}#image: $IMAGE_URL#g" "$MANIFEST" + fi + + sed -E -i "s#imagePullPolicy: .*#imagePullPolicy: Always#g" "$MANIFEST" + + # TODO: harmonize names of the monitoring component + + echo " Deploying '$COMPONENT' component to Kubernetes..." + DEPLOY_LOG="$TMP_LOGS_FOLDER/deploy_${COMPONENT}.log" + kubectl --namespace $TFS_K8S_NAMESPACE apply -f "$MANIFEST" > "$DEPLOY_LOG" + COMPONENT_OBJNAME=$(echo "${COMPONENT}" | sed "s/\_/-/") + #kubectl --namespace $TFS_K8S_NAMESPACE scale deployment --replicas=0 ${COMPONENT_OBJNAME}service >> "$DEPLOY_LOG" + #kubectl --namespace $TFS_K8S_NAMESPACE scale deployment --replicas=1 ${COMPONENT_OBJNAME}service >> "$DEPLOY_LOG" + + echo " Collecting env-vars for '$COMPONENT' component..." + + SERVICE_DATA=$(kubectl get service ${COMPONENT_OBJNAME}service --namespace $TFS_K8S_NAMESPACE -o json) + if [ -z "${SERVICE_DATA}" ]; then continue; fi + + # Env vars for service's host address + SERVICE_HOST=$(echo ${SERVICE_DATA} | jq -r '.spec.clusterIP') + if [ -z "${SERVICE_HOST}" ]; then continue; fi + ENVVAR_HOST=$(echo "${COMPONENT}service_SERVICE_HOST" | tr '[:lower:]' '[:upper:]') + echo "export ${ENVVAR_HOST}=${SERVICE_HOST}" >> $ENV_VARS_SCRIPT + + # Env vars for service's 'grpc' port (if any) + SERVICE_PORT_GRPC=$(echo ${SERVICE_DATA} | jq -r '.spec.ports[] | select(.name=="grpc") | .port') + if [ -n "${SERVICE_PORT_GRPC}" ]; then + ENVVAR_PORT_GRPC=$(echo "${COMPONENT}service_SERVICE_PORT_GRPC" | tr '[:lower:]' '[:upper:]') + echo "export ${ENVVAR_PORT_GRPC}=${SERVICE_PORT_GRPC}" >> $ENV_VARS_SCRIPT + fi + + # Env vars for service's 'http' port (if any) + SERVICE_PORT_HTTP=$(echo ${SERVICE_DATA} | jq -r '.spec.ports[] | select(.name=="http") | .port') + if [ -n "${SERVICE_PORT_HTTP}" ]; then + ENVVAR_PORT_HTTP=$(echo "${COMPONENT}service_SERVICE_PORT_HTTP" | tr '[:lower:]' '[:upper:]') + echo "export ${ENVVAR_PORT_HTTP}=${SERVICE_PORT_HTTP}" >> $ENV_VARS_SCRIPT + fi + + printf "\n" +done + +echo "Deploying extra manifests..." +for EXTRA_MANIFEST in $TFS_EXTRA_MANIFESTS; do + echo "Processing manifest '$EXTRA_MANIFEST'..." + if [[ "$EXTRA_MANIFEST" == *"servicemonitor"* ]]; then + kubectl apply -f $EXTRA_MANIFEST + else + kubectl --namespace $TFS_K8S_NAMESPACE apply -f $EXTRA_MANIFEST + fi + printf "\n" +done +printf "\n" + +for COMPONENT in $TFS_COMPONENTS; do + echo "Waiting for '$COMPONENT' component..." + COMPONENT_OBJNAME=$(echo "${COMPONENT}" | sed "s/\_/-/") + kubectl wait --namespace $TFS_K8S_NAMESPACE \ + --for='condition=available' --timeout=300s deployment/${COMPONENT_OBJNAME}service + printf "\n" +done + +if [[ "$TFS_COMPONENTS" == *"webui"* ]] && [[ "$TFS_COMPONENTS" == *"monitoring"* ]]; then + echo "Configuring WebUI DataStores and Dashboards..." + sleep 5 + + # Exposed through the ingress controller "tfs-ingress" + GRAFANA_URL="127.0.0.1:80/grafana" + + # Default Grafana credentials + GRAFANA_USERNAME="admin" + GRAFANA_PASSWORD="admin" + + # Configure Grafana Admin Password + # Ref: https://grafana.com/docs/grafana/latest/http_api/user/#change-password + GRAFANA_URL_DEFAULT="http://${GRAFANA_USERNAME}:${GRAFANA_PASSWORD}@${GRAFANA_URL}" + + echo ">> Updating Grafana 'admin' password..." + curl -X PUT -H "Content-Type: application/json" -d '{ + "oldPassword": "'${GRAFANA_PASSWORD}'", + "newPassword": "'${TFS_GRAFANA_PASSWORD}'", + "confirmNew" : "'${TFS_GRAFANA_PASSWORD}'" + }' ${GRAFANA_URL_DEFAULT}/api/user/password + echo + echo + + # Updated Grafana API URL + GRAFANA_URL_UPDATED="http://${GRAFANA_USERNAME}:${TFS_GRAFANA_PASSWORD}@${GRAFANA_URL}" + echo "export GRAFANA_URL_UPDATED=${GRAFANA_URL_UPDATED}" >> $ENV_VARS_SCRIPT + + echo ">> Installing Scatter Plot plugin..." + curl -X POST -H "Content-Type: application/json" -H "Content-Length: 0" \ + ${GRAFANA_URL_UPDATED}/api/plugins/michaeldmoore-scatter-panel/install + echo + + # Ref: https://grafana.com/docs/grafana/latest/http_api/data_source/ + QDB_HOST_PORT="${METRICSDB_HOSTNAME}:${QDB_SQL_PORT}" + echo ">> Creating datasources..." + curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -d '{ + "access" : "proxy", + "type" : "postgres", + "name" : "questdb-mon-kpi", + "url" : "'${QDB_HOST_PORT}'", + "database" : "'${QDB_TABLE_MONITORING_KPIS}'", + "user" : "'${QDB_USERNAME}'", + "basicAuth": false, + "isDefault": true, + "jsonData" : { + "sslmode" : "disable", + "postgresVersion" : 1100, + "maxOpenConns" : 0, + "maxIdleConns" : 2, + "connMaxLifetime" : 14400, + "tlsAuth" : false, + "tlsAuthWithCACert" : false, + "timescaledb" : false, + "tlsConfigurationMethod": "file-path", + "tlsSkipVerify" : true + }, + "secureJsonData": {"password": "'${QDB_PASSWORD}'"} + }' ${GRAFANA_URL_UPDATED}/api/datasources + echo + + curl -X POST -H "Content-Type: application/json" -H "Accept: application/json" -d '{ + "access" : "proxy", + "type" : "postgres", + "name" : "questdb-slc-grp", + "url" : "'${QDB_HOST_PORT}'", + "database" : "'${QDB_TABLE_SLICE_GROUPS}'", + "user" : "'${QDB_USERNAME}'", + "basicAuth": false, + "isDefault": false, + "jsonData" : { + "sslmode" : "disable", + "postgresVersion" : 1100, + "maxOpenConns" : 0, + "maxIdleConns" : 2, + "connMaxLifetime" : 14400, + "tlsAuth" : false, + "tlsAuthWithCACert" : false, + "timescaledb" : false, + "tlsConfigurationMethod": "file-path", + "tlsSkipVerify" : true + }, + "secureJsonData": {"password": "'${QDB_PASSWORD}'"} + }' ${GRAFANA_URL_UPDATED}/api/datasources + printf "\n\n" + + echo ">> Creating dashboards..." + # Ref: https://grafana.com/docs/grafana/latest/http_api/dashboard/ + curl -X POST -H "Content-Type: application/json" -d '@src/webui/grafana_db_mon_kpis_psql.json' \ + ${GRAFANA_URL_UPDATED}/api/dashboards/db + echo + + curl -X POST -H "Content-Type: application/json" -d '@src/webui/grafana_db_slc_grps_psql.json' \ + ${GRAFANA_URL_UPDATED}/api/dashboards/db + printf "\n\n" + + echo ">> Staring dashboards..." + DASHBOARD_URL="${GRAFANA_URL_UPDATED}/api/dashboards/uid/tfs-l3-monit" + DASHBOARD_ID=$(curl -s "${DASHBOARD_URL}" | jq '.dashboard.id') + curl -X POST ${GRAFANA_URL_UPDATED}/api/user/stars/dashboard/${DASHBOARD_ID} + echo + + DASHBOARD_URL="${GRAFANA_URL_UPDATED}/api/dashboards/uid/tfs-slice-grps" + DASHBOARD_ID=$(curl -s "${DASHBOARD_URL}" | jq '.dashboard.id') + curl -X POST ${GRAFANA_URL_UPDATED}/api/user/stars/dashboard/${DASHBOARD_ID} + echo + + printf "\n\n" +fi diff --git a/src/bgpls_speaker/requirements.in b/src/bgpls_speaker/requirements.in new file mode 100644 index 000000000..3af49b784 --- /dev/null +++ b/src/bgpls_speaker/requirements.in @@ -0,0 +1,23 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +anytree==2.8.0 +APScheduler==3.8.1 +ncclient==0.6.13 +python-json-logger==2.0.2 +lxml==4.9.1 +pytz==2021.3 +xmltodict==0.12.0 +grpcio==1.47.* +protobuf==3.20.* \ No newline at end of file diff --git a/src/bgpls_speaker/service/BgplsService.py b/src/bgpls_speaker/service/BgplsService.py new file mode 100644 index 000000000..3ac4d1c5b --- /dev/null +++ b/src/bgpls_speaker/service/BgplsService.py @@ -0,0 +1,31 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from bgpls_speaker.service.tools.DiscoveredDBManager import DiscoveredDBManager +from bgpls_speaker.service.tools.GrpcServer import GrpcServer +from common.Constants import ServiceNameEnum +from common.Settings import get_service_port_grpc +from common.proto.bgpls_pb2_grpc import add_BgplsServiceServicer_to_server +from common.tools.service.GenericGrpcService import GenericGrpcService +from .BgplsServiceServicerImpl import BgplsServiceServicerImpl + +class BgplsService(GenericGrpcService): + def __init__(self, discoveredDB : DiscoveredDBManager, + speakerServer : GrpcServer,cls_name: str = __name__) -> None: + port = get_service_port_grpc(ServiceNameEnum.BGPLS) # El enum en common.constants + super().__init__(port, cls_name=cls_name) + self.bgpls_servicer = BgplsServiceServicerImpl(discoveredDB,speakerServer) + + def install_servicers(self): + add_BgplsServiceServicer_to_server(self.bgpls_servicer, self.server) diff --git a/src/bgpls_speaker/service/BgplsServiceServicerImpl.py b/src/bgpls_speaker/service/BgplsServiceServicerImpl.py new file mode 100644 index 000000000..6fa9a8b80 --- /dev/null +++ b/src/bgpls_speaker/service/BgplsServiceServicerImpl.py @@ -0,0 +1,178 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import grpc, json, logging +from typing import List, Tuple, Union +from bgpls_speaker.service.tools.DiscoveredDBManager import DiscoveredDBManager, GetContextDevices, getEndpointFromIpInterface +from bgpls_speaker.service.tools.GrpcServer import GrpcServer +from common.method_wrappers.Decorator import MetricsPool, safe_and_metered_rpc_method +from common.proto.context_pb2 import DeviceId, Empty, EndPointId, Link, LinkId, Uuid +from context.client.ContextClient import ContextClient +from common.proto.bgpls_pb2 import ( + BgplsSpeaker, BgplsSpeakerId, DiscoveredDeviceList, DiscoveredDevice, + DiscoveredLink, DiscoveredLinkList, NodeDescriptors, BgplsSpeakerList +) +from common.proto.bgpls_pb2_grpc import BgplsServiceServicer + +LOGGER = logging.getLogger(__name__) + +METRICS_POOL = MetricsPool('Service', 'RPC') + +class BgplsServiceServicerImpl(BgplsServiceServicer): + def __init__(self,discoveredDB : DiscoveredDBManager, + speakerServer : GrpcServer) -> None: + LOGGER.debug('Creating Servicer...') + self.speaker_handler_factory = 1 + self.speaker_server=speakerServer + self.discoveredDB=discoveredDB + LOGGER.debug('Servicer Created') + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def ListDiscoveredDevices(self, request : Empty, context : grpc.ServicerContext) -> DiscoveredDeviceList: + """ + Get devices discovered from bgpls protocol + """ + device_names=self.discoveredDB.GetNodeNamesFromDiscoveredDB() + nodes = self.discoveredDB.GetNodesFromDiscoveredDB() + devices = [DiscoveredDevice(nodeName=node.node_name,igpID=node.igp_id,learntFrom=node.learnt_from) for node in nodes] + return DiscoveredDeviceList(discovereddevices=devices) + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def ListDiscoveredLinks(self, request : Empty, context : grpc.ServicerContext) -> DiscoveredLinkList: + """ + Get links discovered from bgpls protocol + """ + self.discoveredDB.UpdateNodeNameInLink() + links = self.discoveredDB.GetLinksFromDiscoveredDB() + links_info=[] + for link in links: + local=NodeDescriptors(igp_id=link.local_id,nodeName=link.local_id) + remote=NodeDescriptors(igp_id=link.remote_id,nodeName=link.remote_id) + links_info.append(DiscoveredLink(local=local,remote=remote,learntFrom=link.learnt_from, + local_ipv4=link.local_ipv4_id,remote_ipv4=link.remote_ipv4_id)) + return DiscoveredLinkList(discoveredlinks=links_info) + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def AddBgplsSpeaker(self, request : BgplsSpeaker, context : grpc.ServicerContext) -> BgplsSpeakerId: + """ + Creates a new connection with an speaker with the given ip address, port and as. + Returns de id of the speaker created (to kill proccess¿) + """ + LOGGER.debug("(AddBgplsSpeaker) Create speaker instance %s",request) + + speaker_id=self.speaker_server.connectToJavaBgpls(request.address,request.port,request.asNumber) + return BgplsSpeakerId(id=speaker_id) + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def ListBgplsSpeakers(self, request : Empty, context : grpc.ServicerContext) -> BgplsSpeakerId: + """ + Returns a list of the IDs of the BGP-LS speakers with open connections. + """ + speaker_list=[] + bgpls_speaker_list=[] + speaker_list=self.speaker_server.getSpeakerListIds() + for speaker in speaker_list: + bgpls_speaker_list.append(BgplsSpeakerId(id=speaker)) + return BgplsSpeakerList(speakers=bgpls_speaker_list) + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def DisconnectFromSpeaker(self, request : BgplsSpeaker, context : grpc.ServicerContext) -> bool: + """ + Disconencts from the BGP-LS speaker given its ipv4 address. + """ + speaker_id=self.speaker_server.getSpeakerIdFromIpAddr(request.address) + self.speaker_server.terminateRunnerById(speaker_id) + return Empty() + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def GetSpeakerInfoFromId(self, request : BgplsSpeakerId, context : grpc.ServicerContext) -> BgplsSpeaker: + """ + Get the address, port and as number of the speaker given its id. + """ + address,as_number,port=self.speaker_server.getSpeakerFromId(request.id) + return BgplsSpeaker(address=address,port=port,asNumber=as_number) + + @safe_and_metered_rpc_method(METRICS_POOL, LOGGER) + def NotifyAddNodeToContext(self, request : DiscoveredDevice, context : grpc.ServicerContext) : + """ + When a node is added to context via bgpls module this function checks if there are other nodes in the + topology connected by links discovered via bgpls. Then, if the link exist adds it to the context. + """ + node_name=request.nodeName + node_igp=self.discoveredDB.GetIgpIdFromNodeName(node_name) + LOGGER.debug("(NotifyAddNodeToContext) Find links to nodes %s:%s",node_name,node_igp) + # Get nodes connected and links were the igpID appears + nodes_conected, links_local, links_remote=self.discoveredDB.FindConnectedNodes(node_igp) + o=[LOGGER.debug("(NotifyAddNodeToContext) Links local: %s %s",link_local.local_id, link_local.remote_id) for link_local in links_local] + o=[LOGGER.debug("(NotifyAddNodeToContext) Links remote: %s %s",links_remote.local_id,links_remote.remote_id) for links_remote in links_remote] + # Check if nodes are in context + context_client=ContextClient() + context_client.connect() + # devices=context_client.ListDevices(Empty()) + device_names,devices_ips=GetContextDevices(context_client) + LOGGER.debug("(NotifyAddNodeToContext) Devices in context: %s", device_names) + LOGGER.debug("(NotifyAddNodeToContext) Nodes conected in context: %s", nodes_conected) + nodes_conected_in_context=list(set(nodes_conected) & set(device_names)) + LOGGER.debug("(NotifyAddNodeToContext) nodes_conected_in_context: %s", nodes_conected_in_context) + # TODO: next to function + for remote_node in nodes_conected_in_context: + LOGGER.info("(NotifyAddNodeToContext) creating link to...: %s", remote_node) + remote_igp=self.discoveredDB.GetIgpIdFromNodeName(remote_node) + # Get source device from name + device_uuid_src=DeviceId(device_uuid=Uuid(uuid=node_name)) + device_src=context_client.GetDevice(device_uuid_src) + + # Get destination device from name + device_uuid_dest=DeviceId(device_uuid=Uuid(uuid=remote_node)) + device_dest=context_client.GetDevice(device_uuid_dest) + + # Here I assume one link will always have same link in other direction + # First direction for link + # Get endpoints associated to link between devices + for link_local in links_local: + LOGGER.debug("(NotifyAddNodeToContext) local: %s %s", link_local.local_id,link_local.remote_id) + LOGGER.debug("(NotifyAddNodeToContext) matches: %s %s", node_igp,remote_igp) + if link_local.local_id == node_igp and link_local.remote_id == remote_igp: + LOGGER.debug("(NotifyAddNodeToContext) local_ipv4_id: %s", link_local.local_ipv4_id) + end_point1,ip_1=getEndpointFromIpInterface(device_src,link_local.local_ipv4_id) + LOGGER.debug("(NotifyAddNodeToContext) end_point1: %s", end_point1) + + LOGGER.debug("(NotifyAddNodeToContext) remote_ipv4_id: %s", link_local.remote_ipv4_id) + end_point2,ip_2=getEndpointFromIpInterface(device_dest,link_local.remote_ipv4_id) + LOGGER.debug("(NotifyAddNodeToContext) end_point2: %s", end_point2) + # LOGGER.debug("(NotifyAddNodeToContext) Source: %s Destination: %s", end_point1,end_point2) + + link_name_src_dest=node_name+"/"+end_point1+"=="+remote_node+"/"+end_point2 + + end_point_uuid1=Uuid(uuid=end_point1) + end_point_uuid2=Uuid(uuid=end_point2) + + end_point_id1=EndPointId(endpoint_uuid=end_point_uuid1,device_id=device_uuid_src) + + link_name_dest_src=remote_node+"/"+end_point2+"=="+node_name+"/"+end_point1 + + end_point_id2=EndPointId(endpoint_uuid=end_point_uuid2,device_id=device_uuid_dest) + + end_point_ids_src_dest=[end_point_id1,end_point_id2] + end_point_ids_dest_src=[end_point_id2,end_point_id1] + + link_id_src=context_client.SetLink(Link(link_id=LinkId(link_uuid=Uuid(uuid=link_name_src_dest)), + link_endpoint_ids=end_point_ids_src_dest)) + + link_id_dst=context_client.SetLink(Link(link_id=LinkId(link_uuid=Uuid(uuid=link_name_dest_src)), + link_endpoint_ids=end_point_ids_dest_src)) + + LOGGER.debug("(NotifyAddNodeToContext) Link set id src--->dst: %s", link_id_src) + context_client.close() + return Empty() diff --git a/src/bgpls_speaker/service/__init__.py b/src/bgpls_speaker/service/__init__.py new file mode 100644 index 000000000..f80ccfd52 --- /dev/null +++ b/src/bgpls_speaker/service/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. \ No newline at end of file diff --git a/src/bgpls_speaker/service/__main__.py b/src/bgpls_speaker/service/__main__.py new file mode 100644 index 000000000..a56449eaf --- /dev/null +++ b/src/bgpls_speaker/service/__main__.py @@ -0,0 +1,63 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging, signal, sys, threading +from prometheus_client import start_http_server +from common.Settings import get_log_level, get_metrics_port +from .tools.DiscoveredDBManager import DiscoveredDBManager +from .BgplsService import BgplsService +from .tools.GrpcServer import GrpcServer + +terminate = threading.Event() +LOGGER : logging.Logger = None +_ONE_DAY_IN_SECONDS = 60 * 60 * 24 + +def signal_handler(signal, frame): + LOGGER.warning('Terminate signal received') + LOGGER.warning(signal) + terminate.set() + +def main(): + global LOGGER + + log_level = get_log_level() + logging.basicConfig(level=log_level, format="[%(asctime)s] %(levelname)s:%(name)s:%(message)s") + LOGGER = logging.getLogger(__name__) + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + + LOGGER.info('Starting...') + + # Start metrics server + metrics_port = get_metrics_port() + start_http_server(metrics_port) + # One common database for all bgpls_speakers connection + DB=DiscoveredDBManager() + + speaker_server = GrpcServer(DB) + speaker_server.Connect() + + grpc_service = BgplsService(DB,speaker_server) + grpc_service.start() + + # Wait for termination signal + while not terminate.wait(timeout=0.1): pass + LOGGER.info('Terminating...') + speaker_server.terminateGrpcServer() + grpc_service.stop() + LOGGER.info('Bye') + return 0 + +if __name__ == '__main__': + sys.exit(main()) diff --git a/src/bgpls_speaker/service/java/BGP4Parameters_3.xml b/src/bgpls_speaker/service/java/BGP4Parameters_3.xml new file mode 100644 index 000000000..ec6894922 --- /dev/null +++ b/src/bgpls_speaker/service/java/BGP4Parameters_3.xml @@ -0,0 +1,65 @@ + + + + + 12179 + 7.7.7.7 + + 1112 + + + 10.95.90.43 + false + true + 179 + + + + BGP4Parser2.log + BGP4Client2.log + BGP4Server2.log + + true + + 40000 + true + + + 180 + + 4 + + 65006 + + + + false + + true + + fromBGP + + + + + + 0.0.0.0 + \ No newline at end of file diff --git a/src/bgpls_speaker/service/java/exec_speakear_java.sh b/src/bgpls_speaker/service/java/exec_speakear_java.sh new file mode 100644 index 000000000..10f84c653 --- /dev/null +++ b/src/bgpls_speaker/service/java/exec_speakear_java.sh @@ -0,0 +1,19 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#!/bin/bash +cd netphony-topology/ +"/home/ubuntu/downloads/apache-maven-3.8.8/bin/mvn" clean package -P bgp-ls-speaker assembly:single -DskipTests +cd .. +sudo java -jar netphony-topology/target/bgp-ls-speaker-jar-with-dependencies.jar BGP4Parameters_3.xml \ No newline at end of file diff --git a/src/bgpls_speaker/service/java/netphony-topology/.settings/org.eclipse.jdt.core.prefs b/src/bgpls_speaker/service/java/netphony-topology/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..cb635b1c2 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/src/bgpls_speaker/service/java/netphony-topology/BGP4Parameters_3.xml b/src/bgpls_speaker/service/java/netphony-topology/BGP4Parameters_3.xml new file mode 100644 index 000000000..063344673 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/BGP4Parameters_3.xml @@ -0,0 +1,65 @@ + + + + + 12179 + 7.7.7.7 + + 1112 + + + 10.95.90.43 + false + true + 179 + + + + BGP4Parser2.log + BGP4Client2.log + BGP4Server2.log + + true + + 40000 + true + + + 180 + + 4 + + 100 + + + + false + + true + + fromBGP + + + + + + 0.0.0.0 + \ No newline at end of file diff --git a/src/bgpls_speaker/service/java/netphony-topology/CHANGELOG b/src/bgpls_speaker/service/java/netphony-topology/CHANGELOG new file mode 100644 index 000000000..4049eba8a --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/CHANGELOG @@ -0,0 +1,50 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +v1.3.3 +- Topology Module added +- Topology Module: Export via RESCONF with COP model +- Topology Module: Export via RESTCONF with IETF model (nodes only) +- Topology Module: Export via UNIFY model +- Topology Module: Import via XML +- Topology Module: Import/Export via BGP-LS +v1.3.2 +- Supports network-protocols 1.3.2 +- Update to support reading multiple AS_PATH +- Apache 2.0 license +- Moved to slf4j logging framework +- Added method to pass multiple TEDs from en external program +- Added docker support in travis +v1.3 +- Compile with networking-protocols v1.3.0 (available in maven central) +- JUnit Test upgrade to check intraTEDBs after sending +- Added functionality: read multiple intraTEDBs from xml file +- Added support to draft-previdi-idr-bgpls-te-metric-extensions-00 +v1.2.2 +- Added travis integration +- Javadoc errors fixed +- Ready to meet maven central requirements +- Compile with networking-protocols v1.2.3 (available in maven central) +v1.2.1 +- Compile with networking-protocols v1.2.1 +v1.2 +- JUnit Test added +- Bugfixes +- Reduced number of logs +- Updated README with explanation of parameters +v1.1.1 +- Added configuration instructions of the standalone BGP Peer +- Added dependencies to pom.xml +v1.1.0 +First Public Release diff --git a/src/bgpls_speaker/service/java/netphony-topology/LICENSE b/src/bgpls_speaker/service/java/netphony-topology/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/src/bgpls_speaker/service/java/netphony-topology/VERSION b/src/bgpls_speaker/service/java/netphony-topology/VERSION new file mode 100644 index 000000000..31e5c8434 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/VERSION @@ -0,0 +1 @@ +1.3.3 diff --git a/src/bgpls_speaker/service/java/netphony-topology/doc/Examples.md b/src/bgpls_speaker/service/java/netphony-topology/doc/Examples.md new file mode 100644 index 000000000..88f7a7bd5 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/doc/Examples.md @@ -0,0 +1,133 @@ + + +#Examples + +##Topology Module Examples + +Two sets of basic configuration files are here included with Topology Module software: the setup for running three TM within the same machine (configuration A) and the setup for running three TM in three dedicated machines (configuration B). In both cases three example network topologies are provided to represent the abstract topology of 2 end-point providers and 1 transit provider. + +### Example TM1: 1 Way Test in the same virtual machine, BPG-LS Plugin and UNIFY Export. + +The setup has been provided just for testing purpose and configures 3 TADS in the same machine to perform unidirectional information exchange. + +![1WayTest](figures/1wayTest.png?raw=true "Test with 3 TM") + +The reference files, including Topology Module configuration, BGP-LS Plugin configuration and abstracted topologies are copiend in the folder target/conf1wayTest after the maven installation. Be sure to compile also the Topology Module as indicated in README.md. + +To execute TM1 run: + ```bash + sudo java -Dlog4j.configurationFile=target/log4j2.xml -jar target/topology-1.3.3-shaded.jar target/conf1wayTest/TM1.xml + ``` + +To execute TM2 run: + ```bash + sudo java -Dlog4j.configurationFile=target/log4j2.xml -jar target/topology-1.3.3-shaded.jar target/conf1wayTest/TM2.xml + ``` + +To execute TM3 run: + ```bash + sudo java -Dlog4j.configurationFile=target/log4j2.xml -jar target/topology-1.3.3-shaded.jar target/conf1wayTest/TM3.xml + ``` + +To verify the retrieved information: + ```bash +curl http://localhost:8087/restconf/data/virtualizer/ | python -m json.tool + ``` +[for TADS2] + ```bash +curl http://localhost:8088/restconf/data/virtualizer/ | python -m json.tool + ``` +[for TADS3] + ```bash +curl http://localhost:8089/restconf/data/virtualizer/ | python -m json.tool + ``` + +### Example TM2: 2 Way Test in the different virtual machines, BPG-LS Plugin and UNIFY Export. +The setup has been provided as reference configuration for the configuration of 3 TM in dedicated machines to perform bidirectional exchange of information +![1WayTest](figures/2wayTest.png?raw=true "Test with 3 TM in 3 different machines") +The reference files, including Topology Module configuration, BGP-LS Plugin configuration and abstracted topologies are in + ```bash +target/conf2waysReal + ``` +Before running the reference scenario be sure to complete the IP configuration in the 3 modules, in fact, according to previous description, minor ad-hoc changes are needed. + +In the Topology Module configuration files (TM*.xml): +• set the IP address used for the BGP-LS communication as Identifier + +In the BGP-LS Plugin configuration (BGPLS*_2way.xml): +• set the IP address used for the BGP-LS communication as BGPIdentifier +• configure the peers as needed (IP address and port) + +[where * = 1,2,3] + +To execute TADS1 in machine 1 run: + ```bash + sudo java -Dlog4j.configurationFile=target/log4j2.xml -jar target/topology-1.3.3-shaded.jar target/conf1wayTest/TM1.xml + ``` + +To execute TADS1 in machine 2 run: + ```bash + sudo java -Dlog4j.configurationFile=target/log4j2.xml -jar target/topology-1.3.3-shaded.jar target/conf1wayTest/TM2.xml + ``` + +To execute TADS1 in machine 3 run: + ```bash + sudo java -Dlog4j.configurationFile=target/log4j2.xml -jar target/topology-1.3.3-shaded.jar target/conf1wayTest/TM3.xml + ``` + +To verify the retrieved information: +[for TADS2, in machine 1] + ```bash +curl http://localhost:8088/restconf/data/virtualizer/ | python -m json.tool + ``` +[for TADS2, in machine 2] + ```bash +>curl http://localhost:8088/restconf/data/virtualizer/ | python -m json.tool + ``` +[for TADS3, in machine 3] + ```bash +>curl http://localhost:8088/restconf/data/virtualizer/ | python -m json.tool + ``` +### Topology module with BGP-LS and COP plugins and BGP-LS speaker + +In this example there are 2 BGP-LS speakers, one acting as sender of topology, and the other as consumer. A small topology is loaded from an xml file in BGP-LS Speaker #1. This topology is sent to BGP-LS Speaker #2. + ```bash +TBD + ``` +### Topology module with BGP-LS and COP plugins and Topology module with BGP-LS speaker + +In this example there are 2 BGP-LS speakers, one acting as sender of topology, and the other as consumer. A small topology is loaded from an xml file in BGP-LS Speaker #1. This topology is sent to BGP-LS Speaker #2. + ```bash +TBD + ``` +## BGP-LS Speaker Examples + +### BPP-LS Speaker Example 1 + +In this example there are 2 BGP-LS speakers, one acting as sender of topology, and the other as consumer. A small topology is loaded from an xml file in BGP-LS Speaker #1. This topology is sent to BGP-LS Speaker #2. +To launch BGP-LS Speaker #1: + ```bash +sudo java -Dlog4j.configurationFile=target/log4j2.xml -jar target/bgp-ls-speaker-jar-with-dependencies.jar target/bgpls_example1/BGP4Parameters_1.xml + ``` + BGP-LS Speaker #2: + ```bash +sudo java -Dlog4j.configurationFile=target/log4j2.xml -jar target/bgp-ls-speaker-jar-with-dependencies.jar target/bgpls_example1/BGP4Parameters_2.xml + ``` +To verify the retrieved information: + ```bash +telnet localhost 1112 +show topology + ``` +Then, the topology is printed on screen. diff --git a/src/bgpls_speaker/service/java/netphony-topology/doc/TAPIExample.md b/src/bgpls_speaker/service/java/netphony-topology/doc/TAPIExample.md new file mode 100644 index 000000000..9b0c48c8e --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/doc/TAPIExample.md @@ -0,0 +1,27 @@ + + +# Example 1: TM with XML Plugin and TAPI Plugin +- First of all, compile the full-jar if you have not done so +```bash + mvn package -P generate-full-jar +``` +Execute the server +```bash +sudo java -Dlog4j.configurationFile=target/examples/log4j2.xml -jar target/topology-1.3.4-SNAPSHOT-shaded.jar target/TM_TAPI_example1/TMConfTAPI.xml +``` +Make the query +```bash +curl http://localhost:8089/config/context/topology -X GET -i -H "Content-Type: application/json" -H "Accept: application/json" +``` diff --git a/src/bgpls_speaker/service/java/netphony-topology/doc/TopologyFileDescription.md b/src/bgpls_speaker/service/java/netphony-topology/doc/TopologyFileDescription.md new file mode 100644 index 000000000..452050b65 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/doc/TopologyFileDescription.md @@ -0,0 +1,127 @@ + + +# Topology XML File + +This section describes the topology file format, used by the TADS to load the abstracted view of the local provider. + +The reference file for this description is + +``` +target/conf1wayTest/network1.xml +``` + +The main tag of the file is **network** that can include multiple **domains**, each domain represents a provider. + +```xml + + + + + + +``` + +In this case the network topology includes two providers. + +The first part of the each domain contains some general information: + + - **domain_id**: the AS number of the domain represented in IPv4 format + - the **reachability_entry**: that summarizes the prefix network for the provider (IPv4 network prefix and mask) + - **it_resources**: here the information related to overall IT resources availability is described considering + - **controller_it**: the entry point for 5GEx orchestration + - **cpu**: overall available CPUs + - **mem**: overall available memory + - **storage**: overall available storage + +```xml +0.0.0.1 + + 172.16.101.0 + 24 + + + https://openstack.5Gex.com/url + 100 + 100Gbyte + 100Tbyte + +``` + +Then the file is organized considering a list of nodes and a list unidirectional links. + +Each node is represented with a tag **node** and is identified with an IPv4 id called **router_id** + +```xml + + 172.16.101.101 + + + 172.16.101.102 + + + 172.16.101.103 + + + 172.16.101.104 + +``` + +In the reference case 4 nodes are considered. +Each link is identified by the tag **edge**. +The link description include: + + + - **source**: the source node of the link, identified with the pair **router_id** and interface id, **if_id** + - **destination**: the destination node of the link, identified with the pair router_id and interface + - **TE parameters**: several possibilities are available, in the considered example the focus was on + - unidirectional link delay + - minimum experienced delay + - maximum experienced delay + +```xml + + + 172.16.101.101 + 1 + + + 172.16.101.104 + 1 + + 99 + + 23 + 250 + + + +``` + +For setting up default TE parameters for all the network links, the **edgeCommon** tag is used. + +```xml + + 99 + + 23 + 43 + + 1 + 102 + 802 + 500 + 436 + +``` diff --git a/src/bgpls_speaker/service/java/netphony-topology/doc/figures/1wayTest.png b/src/bgpls_speaker/service/java/netphony-topology/doc/figures/1wayTest.png new file mode 100644 index 0000000000000000000000000000000000000000..021dd3ee5c6dff653af4131f8060e0b7cac88f1d GIT binary patch literal 53545 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 z�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 literal 0 HcmV?d00001 diff --git a/src/bgpls_speaker/service/java/netphony-topology/doc/figures/2wayTest.png b/src/bgpls_speaker/service/java/netphony-topology/doc/figures/2wayTest.png new file mode 100644 index 0000000000000000000000000000000000000000..4800df6d96874c480059be8cc905e753b8614f2b GIT binary patch literal 54450 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 literal 0 HcmV?d00001 diff --git a/src/bgpls_speaker/service/java/netphony-topology/log4j2.xml b/src/bgpls_speaker/service/java/netphony-topology/log4j2.xml new file mode 100644 index 000000000..d0b383697 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/log4j2.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/bgpls_speaker/service/java/netphony-topology/pom.xml b/src/bgpls_speaker/service/java/netphony-topology/pom.xml new file mode 100644 index 000000000..be949361d --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/pom.xml @@ -0,0 +1,497 @@ + + + 4.0.0 + es.tid.netphony + topology + 1.4.0-SNAPSHOT + jar + Netphony TED and BGP-LS peer + Traffic Engineering Database, BGP-LS peer, Topology Module + http://telefonicaid.github.io/netphony-topology/ + + + Apache License 2.0 + http://www.apache.org/licenses/LICENSE-2.0 + + + + + + + + + + + + + + + + + + + com.sun.jersey + jersey-json + ${jersey-version} + + + + org.slf4j + slf4j-api + ${slf4j-version} + + + + org.slf4j + slf4j-simple + ${slf4j-version} + + + es.tid.netphony + network-protocols + 1.4.1 + + + + + org.jgrapht + jgrapht-core + ${jgrapht-core-version} + + + com.google.code.gson + gson + 2.2.2 + + + com.googlecode.json-simple + json-simple + 1.1.1 + + + com.metaparadigm + json-rpc + 1.0 + + + redis.clients + jedis + 2.1.0 + + + + com.fasterxml.jackson.core + jackson-core + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson-version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson-version} + + + com.fasterxml.jackson.datatype + jackson-datatype-joda + ${jackson-datatype-joda-version} + + + + joda-time + joda-time + ${jodatime-version} + + + + + io.grpc + grpc-netty-shaded + ${grpc-protobuf-version} + + + io.grpc + grpc-protobuf + ${grpc-protobuf-version} + + + io.grpc + grpc-stub + ${grpc-stub-version} + + + javax.annotation + javax.annotation-api + ${javax-annotation-api-version} + + + + com.google.guava + guava + 31.1-jre + + + + + + Telefonica I+D + oscar.gonzalezdedios@telefonica.com + Telefonica I+D + https://www.tid.es + + + + scm:git:git@github.com:telefonicaid/netphony-topology.git + scm:git:git@github.com:telefonicaid/netphony-topology.git + git@github.com:telefonicaid/netphony-topology.git + + + + + oss.sonatype.org-snapshot + http://oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + ${basedir}/src/main/java + + + kr.motd.maven + os-maven-plugin + 1.6.2 + + + + + + org.xolstice.maven.plugins + protobuf-maven-plugin + 0.6.1 + + com.google.protobuf:protoc:3.9.0:exe:${os.detected.classifier} + grpc-java + io.grpc:protoc-gen-grpc-java:1.24.0:exe:${os.detected.classifier} + + + + + compile + compile-custom + + + + + + maven-compiler-plugin + 3.8.1 + + 8 + 8 + UTF-8 + + + + maven-resources-plugin + 2.6 + + UTF-8 + + + + copy-resources + validate + + copy-resources + + + ${basedir}/target + + + ${basedir}/src/main/resources + true + + + ${basedir}/src/main/sample-config-files + true + + + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.0 + + + + true + lib/ + eu.teraflow.tid.bgp4Peer.peer.BGPPeerMain + + + + + + + + + deploy-maven-central + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + -Xdoclint:none + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + verify + + sign + + + + + + + + + bgp-ls-speaker + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.5 + + + org.apache.logging.log4j + log4j-api + 2.5 + + + org.apache.logging.log4j + log4j-core + 2.5 + + + io.netty + netty-transport-native-epoll + 4.1.77.Final + linux-x86_64 + + + + + + maven-assembly-plugin + 3.3.0 + + + jar-with-dependencies + + bgp-ls-speaker + + + eu.teraflow.tid.bgp4Peer.peer.BGPPeerMain + + + + + + + + + generate-javadoc + + + + org.apache.maven.plugins + maven-javadoc-plugin + + false + + 2.9.1 + + + attach-javadocs + + jar + + + + + + + + + integration-test + + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.13 + + + integration-test + + integration-test + + + + verify + + verify + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.19.1 + + true + + + + + + + + generate-full-jar + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.5 + + + org.apache.logging.log4j + log4j-api + 2.5 + + + org.apache.logging.log4j + log4j-core + 2.5 + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.4.3 + + + package + + shade + + + true + + + *:* + + + + false + + + + eu.teraflow.tid.bgp.bgp4Peer.peer.BGPPeerMain + + + + + + + make-assembly + package + + single + + + + + + + + + + + 1.19.4 + 2.0.6 + 4.8.1 + 2.5 + 2.4.2 + 2.3 + 2.19.1 + 0.9.1 + 1.3.2 + 1.24.0 + 1.46.0 + 2.1.5 + + diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4PeerInitiatedSession.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4PeerInitiatedSession.java new file mode 100644 index 000000000..e5a37e743 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4PeerInitiatedSession.java @@ -0,0 +1,188 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.bgp4session; + +import es.tid.bgp.bgp4.messages.BGP4Message; +import es.tid.bgp.bgp4.messages.BGP4MessageTypes; +import es.tid.bgp.bgp4.messages.BGP4Update; +import eu.teraflow.tid.bgp4Peer.peer.BGP4Exception; +import eu.teraflow.tid.bgp4Peer.updateTEDB.UpdateDispatcher; + +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.Inet4Address; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketException; +import java.util.Timer; + +/** + * BGP4 session server + * + * @author mcs + * + */ +public class BGP4PeerInitiatedSession extends GenericBGP4Session{ + /** + * Class to dispatch the BGP4 update messages. + * If a BGP5 update message is received, it is stored in a queue of UpdateDispatcher. + */ + private UpdateDispatcher updateDispatcher; + + + /** + * Constructor of the BGP4 Session + * @param s Socket of the BGP4Peer-BGP4Peer Communication + * @param bgp4SessionsInformation bgp4SessionsInformation + * @param updateDispatcher updateDispatcher + * @param holdTime holdTime + * @param BGPIdentifier BGPIdentifier + * @param version version + * @param myAutonomousSystem myAutonomousSystem + * @param noDelay noDelay + * @param keepAliveTimer keepAliveTimer + */ + public BGP4PeerInitiatedSession(Socket s, BGP4SessionsInformation bgp4SessionsInformation, UpdateDispatcher updateDispatcher,int holdTime,Inet4Address BGPIdentifier,int version,int myAutonomousSystem,boolean noDelay,int keepAliveTimer ){ + super(bgp4SessionsInformation, holdTime, BGPIdentifier, version, myAutonomousSystem,keepAliveTimer); + + this.setFSMstate(BGP4StateSession.BGP4_STATE_IDLE); + log=LoggerFactory.getLogger("BGP4Server"); + log.debug("New BGP4Session: "+s); + this.socket = s; + try { + s.setTcpNoDelay(noDelay); + } catch (SocketException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + this.newSessionId(); + + this.remotePeerIP =(Inet4Address) ((InetSocketAddress) socket.getRemoteSocketAddress()).getAddress(); + + + timer=new Timer(); + this.updateDispatcher = updateDispatcher; + //this.keepAliveLocal=params.getKeepAliveTimer(); + //this.deadTimerLocal=params.getDeadTimer(); + } + + + + /** + * Initiates a Session the BGP-4 Peers + */ + public void run() { + try { + initializeBGP4Session(); + } catch (BGP4Exception e2) { + // TODO Auto-generated catch block + try { + this.socket.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return; + } + log.info("BGP4 Session established with peer "+this.remotePeerIP); + this.deadTimerT=new DeadTimerThread(this, this.holdTime); + startDeadTimer(); + this.keepAliveT=new KeepAliveThread(out, this.keepAliveTimer); + startKeepAlive(); + + //Listen to new messages + try{ + while(this.FSMstate==BGP4StateSession.BGP4_STATE_SESSION_UP) { + try { + this.msg = readBGP4Msg(in);//Read a new message + + }catch (IOException e){ + cancelDeadTimer(); + cancelKeepAlive(); + timer.cancel(); + try { + in.close(); + out.close(); + } catch (Exception e1) { + log.warn("Exception Closing BGP4 Session with "+this.remotePeerIP); + } + log.debug("Finishing BGP4 Session with "+this.remotePeerIP); + return; + } + if (this.msg != null) {//If null, it is not a valid PCEP message + boolean bgp4Msg = true;//By now, we assume a valid PCEP message has arrived + //Depending on the type a different action is performed + switch(BGP4Message.getMessageType(this.msg)) { + + case BGP4MessageTypes.MESSAGE_OPEN: + log.debug("OPEN message received"); + //After the session has been started, ignore subsequent OPEN messages + log.warn("OPEN message ignored"); + break; + + case BGP4MessageTypes.MESSAGE_KEEPALIVE: + log.debug("KEEPALIVE message received from "+this.remotePeerIP); + //The Keepalive message allows to reset the deadtimer + break; + + case BGP4MessageTypes.MESSAGE_NOTIFICATION: + log.info("NOTIFICATION message from "+this.remotePeerIP); + break; + + case BGP4MessageTypes.MESSAGE_UPDATE: + log.debug("UPDATE message from "+this.remotePeerIP); + BGP4Update bgp4Update = new BGP4Update(msg); + log.debug(bgp4Update.toString()); + bgp4Update.setLearntFrom(this.getRemotePeerIP().toString()); + updateDispatcher.dispatchRequests(bgp4Update); + break; + + default: + log.warn("ERROR: unexpected message from "+this.remotePeerIP); + bgp4Msg = false; + } + + if (bgp4Msg) { + //Reseting Dead Timer as BGP4 Session Message has arrived + resetDeadTimer(); + } + } + } + }finally{ + log.error("BGP4 session with peer "+this.remotePeerIP+" has been closed"); + cancelDeadTimer(); + cancelKeepAlive(); + this.FSMstate=BGP4StateSession.BGP4_STATE_IDLE; + endSession(); + } + } + + @Override + public void close() { + // TODO Auto-generated method stub + + } + + + + @Override + protected void endSession() { + // TODO Auto-generated method stub + log.debug("Ending session with id "+this.getSessionId()+" from peer "+this.remotePeerIP); + BGP4SessionsInformation.deleteSession(this.getSessionId()); + } + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4Session.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4Session.java new file mode 100644 index 000000000..002a5caa5 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4Session.java @@ -0,0 +1,44 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.bgp4session; + +import es.tid.bgp.bgp4.messages.BGP4Message; + + +/** + * BGP Session Interface + * + * @author mcs + * + */ +public interface BGP4Session { + /** + * Send close message and finish the BGP Session + */ + public void close(/*int reason*/); + /** + * Finish the BGP Session abruptly, + */ + public void killSession(); + + /** + * Encodes and sends BGP Message + * If the message is bad encoded, the session is closed + * @param message BGP4 Message + */ + public void sendBGP4Message(BGP4Message message); + + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionClient.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionClient.java new file mode 100644 index 000000000..61a5fc41c --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionClient.java @@ -0,0 +1,222 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.bgp4session; + +import es.tid.bgp.bgp4.messages.BGP4Message; +import es.tid.bgp.bgp4.messages.BGP4MessageTypes; +import es.tid.bgp.bgp4.messages.BGP4Update; +import eu.teraflow.tid.bgp4Peer.peer.BGP4Exception; +import eu.teraflow.tid.bgp4Peer.updateTEDB.UpdateDispatcher; + +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.Inet4Address; +import java.net.Socket; +import java.util.Timer; +/** + * Client session + * + * @author mcs + * + */ +public class BGP4SessionClient extends GenericBGP4Session{ + /** + * Peer BGP port to which the session is connected + */ + private int peerBGP_port; + /** + * Delay + */ + + + private boolean no_delay=true; + private String localBGP4Address; + private int localBGP4Port; + /** + * Class to dispatch the BGP4 update messages. + * If a BGP5 update message is received, it is stored in a queue of UpdateDispatcher. + */ + private UpdateDispatcher updateDispatcher; + + public BGP4SessionClient(BGP4SessionsInformation bgp4SessionsInformation,UpdateDispatcher updateDispatcher, Inet4Address peerBGP_IPaddress, int peerBGP_port, int holdTime,Inet4Address BGPIdentifier,int version,int myAutonomousSystem, String localBGP4Address, int localBGP4Port,int keepAliveTimer){ + super(bgp4SessionsInformation, holdTime, BGPIdentifier, version, myAutonomousSystem,keepAliveTimer); + timer=new Timer(); + log = LoggerFactory.getLogger("BGP4Client"); + this.peerBGP_port = peerBGP_port; + this.updateDispatcher=updateDispatcher; + this.localBGP4Address=localBGP4Address; + this.localBGP4Port=localBGP4Port; + this.remotePeerIP = peerBGP_IPaddress; + } + /** + * Initiates a Session between the local BGP Peer and the remote BGP Peer + */ + public void run() { + + log.info("Opening new BGP4 Session with host "+ this.remotePeerIP.getHostAddress() + " on port " + this.peerBGP_port); + log.debug("Do we want to update from peer?" + updateFrom); + log.debug("Do we want to send to peer?" + sendTo); + try { + Inet4Address addr = (Inet4Address) Inet4Address.getByName(localBGP4Address); + Inet4Address addrPeer = remotePeerIP; + socket = new Socket(addrPeer, peerBGP_port, addr, 0); + if (no_delay){ + this.socket.setTcpNoDelay(true); + log.debug("No delay activated"); + } + + } catch (IOException e) { + log.info("Connection refused trying to connect " + remotePeerIP.getHostAddress() + " on port " + peerBGP_port); + //As there is not yet a session added (it is added in the beginning of initializeBGP4Session()); + //endSession(); + return; + } + + try { + initializeBGP4Session(); + log.info("BGP4 Session established with peer "+this.remotePeerIP); + this.keepAliveT= new KeepAliveThread(this.getOut(),this.keepAliveTimer); + keepAliveT.start(); + } catch (BGP4Exception e2) { + // TODO Auto-generated catch block + e2.printStackTrace(); + log.debug("Session with "+this.remotePeerIP+" already exists: "+e2.getMessage()); + try { + socket.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + log.error("Problem closing socket "+e.getMessage()); + } + return; + } + + + + + try{ + while(this.FSMstate==BGP4StateSession.BGP4_STATE_SESSION_UP) { + try { + + this.msg = readBGP4Msg(in);//Read a new message + + }catch (IOException e){ + cancelDeadTimer(); + cancelKeepAlive(); + timer.cancel(); + try { + in.close(); + out.close(); + } catch (Exception e1) { + log.warn("problem closing sockets"); + } + log.debug("Finishing BGP4 Session abruptly!"); + return; + } + if (this.msg != null) {//If null, it is not a valid PCEP message + boolean bgp4Msg = true;//By now, we assume a valid PCEP message has arrived + //Depending on the type a different action is performed + switch(BGP4Message.getMessageType(this.msg)) { + + case BGP4MessageTypes.MESSAGE_OPEN: + log.debug("BGP OPEN message received from "+this.remotePeerIP); + //After the session has been started, ignore subsequent OPEN messages + log.warn("OPEN message ignored"); + break; + + case BGP4MessageTypes.MESSAGE_KEEPALIVE: + log.debug("BGP KEEPALIVE message received from "+this.remotePeerIP); + //The Keepalive message allows to reset the deadtimer + break; + + case BGP4MessageTypes.MESSAGE_NOTIFICATION: + log.debug("BGP NOTIFICATION message received from "+this.remotePeerIP); + break; + + case BGP4MessageTypes.MESSAGE_UPDATE: + log.debug("BGP UPDATE message received from "+this.remotePeerIP); + if(this.getUpdateFrom()){ + BGP4Update bgp4Update = new BGP4Update(msg); + log.debug(bgp4Update.toString()); + bgp4Update.setLearntFrom(this.remotePeerIP.getHostAddress() ); + updateDispatcher.dispatchRequests(bgp4Update); + } + else + log.debug("Update message from " + this.remotePeerIP + " discarded"); + break; + + default: + log.warn("ERROR: unexpected message received"); + bgp4Msg = false; + } + + if (bgp4Msg) { + //Reseting Dead Timer as BGP4 Session Message has arrived + resetDeadTimer(); + } + } + } + }finally{ + //log.error("SESSION "+ internalSessionID+" IS KILLED"); + log.info("BGP4 session with peer "+this.remotePeerIP+" has been closed"); + cancelDeadTimer(); + cancelKeepAlive(); + this.FSMstate=BGP4StateSession.BGP4_STATE_IDLE; + endSession(); + } + } + + + public int getPeerBGP_port() { + return peerBGP_port; + } + public void setPeerBGP_port(int peerBGP_port) { + this.peerBGP_port = peerBGP_port; + } + public Boolean getUpdateFrom() { + return updateFrom; + } + public void setUpdateFrom(Boolean updateFrom) { + this.updateFrom = updateFrom; + } + public Boolean getSendTo() { + return sendTo; + } + public void setSendTo(Boolean sendTo) { + this.sendTo = sendTo; + } + public boolean isNo_delay() { + return no_delay; + } + public void setNo_delay(boolean no_delay) { + this.no_delay = no_delay; + } + + + @Override + public void close() { + // TODO Auto-generated method stub + + } + + + @Override + protected void endSession() { + // TODO Auto-generated method stub + log.debug("Ending session with id "+this.getSessionId()); + this.BGP4SessionsInformation.deleteSession(this.getSessionId()); + } + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionExistsException.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionExistsException.java new file mode 100644 index 000000000..668825ca8 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionExistsException.java @@ -0,0 +1,24 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.bgp4session; + +public class BGP4SessionExistsException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1L; + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionsInformation.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionsInformation.java new file mode 100644 index 000000000..df5d7bc9c --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4SessionsInformation.java @@ -0,0 +1,146 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.bgp4session; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import eu.teraflow.tid.bgp4Peer.peer.BGP4Exception; + +import java.io.DataOutputStream; +import java.net.Inet4Address; +import java.util.Enumeration; +import java.util.Hashtable; + + +/** + * Class where the oppened BGP4 sessions are stored. + * + * @author mcs + * + */ +public class BGP4SessionsInformation { + public Hashtable sessionList; + public Hashtable sessionListByPeerIP; + private boolean isTest = false; + Logger log; + //FIXME: ya lo tenemos a trav�s de la lista de sesiones + DataOutputStream out; + + public BGP4SessionsInformation(){ + sessionList=new Hashtable(); + sessionListByPeerIP=new Hashtable(); + log = LoggerFactory.getLogger("BGP4Parser"); + } + + public BGP4SessionsInformation(boolean test){ + sessionList=new Hashtable(); + sessionListByPeerIP=new Hashtable(); + log = LoggerFactory.getLogger("BGP4Parser"); + isTest= test; + } + + + public synchronized void notifySessionStart(Inet4Address addr) throws BGP4SessionExistsException{ + if (sessionListByPeerIP.containsKey(addr)){ + throw new BGP4SessionExistsException(); + } + } + + public synchronized void addSession(long sessionId, GenericBGP4Session session) throws BGP4Exception{ + Enumeration sessions = sessionList.elements(); + log.debug("Looking to add session with id "+sessionId+" --> "+session.toString()); + + //Check if there is already a session with the remote peer. + //Only one session allowed with each remote peer + GenericBGP4Session existingSession=sessionListByPeerIP.get(session.remotePeerIP); + if(isTest){ + //If there is no existing session with the peer + sessionList.put(new Long(sessionId),session); + sessionListByPeerIP.put(session.getPeerIP() , session); + log.debug("Registering new session with Peer "+session.getPeerIP() +" with ID "+sessionId); + } + else{ + if (existingSession!=null){ + log.debug("Session with id "+existingSession.getSessionId()+" against "+session.remotePeerIP.getHostAddress()+" already exists"); + throw new BGP4Exception();//si no existe throw new BGP4Exception(); + } + + //If there is no existing session with the peer + sessionList.put(new Long(sessionId),session); + sessionListByPeerIP.put(session.getPeerIP() , session); + log.debug("Registering new session with Peer "+session.getPeerIP() +" with ID "+sessionId); + + } + + } + + public synchronized void deleteSession(long sessionId){ + GenericBGP4Session ses=sessionList.get(sessionId); + if (ses!=null) { + Inet4Address ip=sessionList.get(sessionId).getPeerIP(); + sessionList.remove(new Long(sessionId)); + sessionListByPeerIP.remove(ses.getPeerIP()); + log.debug("Deleted Session with id "+sessionId +" with peer "+ses.getPeerIP().getHostAddress()); + }else { + log.info("SESSION WAS NOT REGISTERED NULL"); + } + + + } + + @Override + public String toString() { + StringBuffer sb=new StringBuffer(2000); + int counter = 1; + Enumeration sessions = sessionList.elements(); + + //Comprobar si ya existe la session con ese peer + while (sessions.hasMoreElements()){ + sb.append("Session number "+(counter++)+"\n"); + sb.append(sessions.nextElement().toString()+"\n"); + + } + return sb.toString(); + } + + public String printSession(long sessionId){ + GenericBGP4Session ses=sessionList.get(new Long(sessionId)); + if (ses!=null){ + return ses.toString(); + }else { + return "session "+sessionId+" does not exist"; + } + } + + + + public DataOutputStream getOut() { + return out; + } + + public void setOut(DataOutputStream out) { + this.out = out; + } + + public Hashtable getSessionList() { + return sessionList; + } + public void setSessionList(Hashtable sessionList) { + this.sessionList = sessionList; + } + + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4StateSession.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4StateSession.java new file mode 100644 index 000000000..6f426828b --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/BGP4StateSession.java @@ -0,0 +1,28 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.bgp4session; +/** + * The state session attribute indicates the current state of the BGP + FSM + * @author mcs + * + */ +public class BGP4StateSession { + public static final int BGP4_STATE_IDLE=0; + public static final int BGP4_STATE_TCP_PENDING=1; + public static final int BGP4_STATE_OPEN_WAIT=2; + public static final int BGP4_STATE_KEEP_WAIT=3; + public static final int BGP4_STATE_SESSION_UP=4; +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/ConnectRetryTimer.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/ConnectRetryTimer.java new file mode 100644 index 000000000..736c56fc5 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/ConnectRetryTimer.java @@ -0,0 +1,30 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.bgp4session; + +import java.util.TimerTask; + +public class ConnectRetryTimer extends TimerTask { + int initialValue; + ConnectRetryTimer(int initialValue){ + this.initialValue=initialValue; + } + @Override + public void run() { + // TODO Auto-generated method stub + + } + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/DeadTimerThread.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/DeadTimerThread.java new file mode 100644 index 000000000..f32f0218f --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/DeadTimerThread.java @@ -0,0 +1,72 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.bgp4session; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * BGP4 DeadTimer management Thread + * + */ +public class DeadTimerThread extends Thread { + + + private BGP4Session bgp4Session = null; + private int deadTimer = 0; + private Logger log; + private boolean running; + + public DeadTimerThread(BGP4Session p, int d) { + this.deadTimer = d; + this.bgp4Session = p; + log=LoggerFactory.getLogger("BGP4Server"); + } + + public void run() { + running=true; + while (running) { + try { + sleep(deadTimer * 1000); + /* + * Time's over, close PCEP Session + */ + log.warn("DeadTimer OVER"); + this.bgp4Session.close(/*ObjectParameters.REASON_DEADTIMER*/); + return; + } catch (InterruptedException e) { + //return; + if (running==false){ + log.debug("Ending DeadTimerThread"); + return; + } + else { + log.debug("Reseting Dead Timer"); + } + } catch (Exception e) { + //FIXME: Ver que hacer aqui, por ahora, solo saco un log + log.warn("Unhandled exception: " + e.getMessage()); + } + + } + + + } + + public void stopRunning(){ + running=false; + } +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/GenericBGP4Session.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/GenericBGP4Session.java new file mode 100644 index 000000000..45636a2fe --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/GenericBGP4Session.java @@ -0,0 +1,908 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.bgp4session; + +import es.tid.bgp.bgp4.messages.BGP4Keepalive; +import es.tid.bgp.bgp4.messages.BGP4Message; +import es.tid.bgp.bgp4.messages.BGP4MessageTypes; +import es.tid.bgp.bgp4.messages.BGP4Open; +import es.tid.bgp.bgp4.open.BGP4CapabilitiesOptionalParameter; +import es.tid.bgp.bgp4.open.BGP4OctetsASByteCapabilityAdvertisement; +import es.tid.bgp.bgp4.open.MultiprotocolExtensionCapabilityAdvertisement; +import es.tid.bgp.bgp4.update.fields.pathAttributes.AFICodes; +import es.tid.bgp.bgp4.update.fields.pathAttributes.SAFICodes; +import eu.teraflow.tid.bgp4Peer.peer.BGP4Exception; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.Inet4Address; +import java.net.Socket; +import java.util.Timer; + + +/** + * Generic BGP4 Session. + * Implements the basics of a BGP4 Session + * Any particular session must inherit this one + * + * @author ogondio + * + */ +public abstract class GenericBGP4Session extends Thread implements BGP4Session { + + /** + * PCEP Session Manager + */ + protected BGP4SessionsInformation BGP4SessionsInformation; + + /** + * Thread to send periodic Keepalives + */ + protected KeepAliveThread keepAliveT = null; + + /** + * Value of the Keepalive timer set by the Local PCE. Used to send keepalives + */ + + protected int keepAliveLocal; + + /** + * Value of the Keepalive timer of the peer PCC. It is not used in the server!!! + */ + protected int keepAlivePeer; + + /** + * Thread to check if the connection is still alive. + * If in this time the PCE has not received anything, it closes the session + * It is set by the PCC (in this case, the remote peer) + */ + protected DeadTimerThread deadTimerT = null; + + /** + * Value of the deadtimer that the PCC sends. It is used in the PCC in the thread + */ + protected int deadTimerPeer; + + /** + * Socket of the communication between BGP peers + */ + protected Socket socket = null; + + /** + * Remote Peer IP Address + * Obtained from the socket for convenience + */ + protected Inet4Address remotePeerIP=null; + + /** + * DataOutputStream to send messages to the peer + */ + protected DataOutputStream out=null; + + + + /** + * DataInputStream to receive messages from PCC + */ + protected DataInputStream in=null;// + /** + * Queue to send the Computing Path Requests + */ + //protected RequestQueueSend req; + + /** + * Logger to write the Parent PCE server log + */ + protected Logger log; + + /** + * Timer to schedule KeepWait and OpenWait Timers + */ + protected Timer timer; + + /** + * Finite State Machine of the PCEP protocol + */ + protected int FSMstate; + + /** + * Remote Domain ID + * null if not sent + */ + protected Inet4Address remoteDomainId=null; + + /** + * Remote List of OF Codes + * If sent by the peer PCE + */ + //private LinkedList remoteOfCodes;//FIME: What do we do with them? + + /** + * RemoteOK: a boolean that is set to 1 if the system has received an + acceptable Open message. + */ + private boolean remoteOK=false; + + /** + * + */ + private boolean localOK=false; + + /** + * + */ + private int openRetry=0; + + /** + * Byte array to store the last PCEP message read. + */ + protected byte[] msg = null; + + /** + * Initial number of the session ID (internal use only) + */ + public static long sessionIdCounter=0; + + /** + * + */ + protected Boolean updateFrom; + protected boolean sendTo; + + /** + * Session ID (internal use only) + */ + private long sessionId; + /**************** PARAMETROS DE LA SESION ********************/ + private int ConnectRetryCounter=0; + private ConnectRetryTimer connectRetryTimer = null; + private int connectRetryTime; //FIXME: esto aun no se que es. + + /**************PARAMETROS OPEN MESSAGE************************/ + protected int holdTime; + /** + * Time between sending keepalives + */ + protected int keepAliveTimer; + /** + * IP address that is assigned to that BGP speaker + */ + protected Inet4Address BGPIdentifier; + /** + * Autonomous System number of the sender + */ + protected int myAutonomousSystem; + /** + * version indicates the protocol version number of the message + * it must be 4 + */ + protected int version; + + + public GenericBGP4Session(BGP4SessionsInformation bgp4SessionsInformation,int holdTime,Inet4Address BGPIdentifier,int version,int myAutonomousSystem,int mykeepAliveTimer) { + log=LoggerFactory.getLogger("BGP4Parser"); + this.BGP4SessionsInformation=bgp4SessionsInformation; + this.holdTime=holdTime; + this.BGPIdentifier=BGPIdentifier; + this.version = version; + this.myAutonomousSystem=myAutonomousSystem; + this.keepAliveTimer = mykeepAliveTimer; + this.newSessionId(); + + } + + /** + * Read PCE message from TCP stream + * @param in InputStream + * @return byte array with a BGP4 Message + * @throws IOException Execption thrown trying to read message + */ + protected byte[] readBGP4Msg(DataInputStream in) throws IOException{ + byte[] ret = null; + + byte[] hdr = new byte[BGP4Message.getBGPHeaderLength()]; + byte[] temp = null; + boolean endHdr = false; + int r = 0; + int length = 0; + boolean endMsg = false; + int offset = 0; + + while (!endMsg) { + try { + if (endHdr) { + r = in.read(temp, offset, 1); + } + else { + r = in.read(hdr, offset, 1); + } + } catch (IOException e){ + log.warn("Error reading data: "+ e.getMessage()); + throw e; + }catch (Exception e) { + log.warn("readMsg Oops: " + e.getMessage()); + throw new IOException(); + } + + if (r > 0) { + if (offset == BGP4Message.getBGPMarkerLength()) { + length = ((int)hdr[offset]&0xFF) << 8; + } + if (offset == BGP4Message.getBGPMarkerLength() + 1) { + length = length | (((int)hdr[offset]&0xFF)); + temp = new byte[length]; + endHdr = true; + System.arraycopy(hdr, 0, temp, 0, BGP4Message.getBGPHeaderLength()); + } + if ((length > 0) && (offset == length - 1)) { + endMsg = true; + } + offset++; + } + else if (r==-1){ + log.debug("End of stream has been reached"); + throw new IOException(); + } + } + if (length > 0) { + ret = new byte[length]; + System.arraycopy(temp, 0, ret, 0, length); + } + return ret; + } + + /** + * Read PCE message from TCP stream + * @param in InputStream + * @return byte array with a BGP4 Message + * @throws IOException Execption thrown trying to read message + */ + protected byte[] readMsgOptimized(DataInputStream in) throws IOException{ + byte[] ret = null; + + byte[] hdr = new byte[4]; + byte[] temp = null; + boolean endHdr = false; + int r = 0; + int length = 0; + boolean endMsg = false; + int offset = 0; + + + while (!endMsg) { + try { + if (endHdr) { + //log.info("Vamos a leer datos "); + r = in.read(temp, offset, length-offset); + if (r>0){ + if ((offset+r)>=length){ + //log.info("Bien "); + endMsg=true; + }else { + offset=offset+r; + } + + } + else if (r<0){ + log.error("End of stream has been reached reading data"); + throw new IOException(); + } + } + else { + //log.info("Vamos a leer la cabecera "); + r = in.read(hdr, offset, 4-offset); + if (r < 0) { + log.error("End of stream has been reached reading header"); + throw new IOException(); + }else if (r >0){ + if ((offset+r)>=4){ + length = ( (hdr[offset+2]&0xFF) << 8) | ((hdr[offset+3]&0xFF)); + offset=4; + temp = new byte[length]; + endHdr = true; + System.arraycopy(hdr, 0, temp, 0, 4); + if (length==4){ + endMsg=true; + } + }else { + offset=offset+r; + } + + } + + } + } catch (IOException e){ + log.error("Error reading data: "+ e.getMessage()); + throw e; + }catch (Exception e) { + log.error("readMsg Oops: " + e.getMessage()); + log.error("Failure reason : "+e.getStackTrace()); + throw new IOException(); + } + + } + if (length > 0) { + ret = new byte[length]; + System.arraycopy(temp, 0, ret, 0, length); + } + return ret; + } + + + // /** + // *

Close the PCE session

+ // *

List of reasons (RFC 5440):

+ // * Value Meaning + // 1 No explanation provided + // 2 DeadTimer expired + // 3 Reception of a malformed PCEP message + // 4 Reception of an unacceptable number of unknown + // requests/replies + // 5 Reception of an unacceptable number of unrecognized + // PCEP messages + // * @param reason Reason for closing the PCEP Session + // * @return PCEP Session closed OK + // */ + // public void close(int reason){ + // log.info("Closing PCEP Session"); + // BGP4Close p_close=new BGP4Close(); + // p_close.setReason(reason); + // sendPCEPMessage(p_close); + // killSession(); + // } + public DataOutputStream getOut() { + return out; + } + + public void setOut(DataOutputStream out) { + this.out = out; + } + + /** + * Starts the deadTimerThread + */ + protected void startDeadTimer() { + this.deadTimerT.start(); + } + /** + * Resets the DeadTimerThread + * To be called every time a message in the session is received + */ + protected void resetDeadTimer() { + if (this.deadTimerT != null) { + this.deadTimerT.interrupt(); + } + } + + public Socket getSocket() { + return socket; + } + + /** + * Ends the DeadTimer Thread + */ + protected void cancelDeadTimer() { + log.debug("Cancelling DeadTimer"); + if (this.deadTimerT != null) { + this.deadTimerT.stopRunning(); + this.deadTimerT.interrupt(); + this.deadTimerT=null; + } + } + + /** + * Starts the Keep Alive Thread + */ + public void startKeepAlive() { + this.keepAliveT.start(); + } + + /** + * Ends the KeepAlive Thread + */ + public void cancelKeepAlive() { + log.debug("Cancelling KeepAliveTimer"); + if (this.keepAliveT != null) { + this.keepAliveT.stopRunning(); + this.keepAliveT.interrupt(); + this.keepAliveT=null; + } + } + + /** + * Ends current connections + */ + protected void endConnections(){ + try { + if (in != null) { + in.close(); + } + if (out != null) { + out.close(); + } + if (this.socket != null) { + log.warn("Closing socket"); + this.socket.close(); + } + + } catch (Exception e) { + log.warn("Error closing connections: " + e.getMessage()); + } + } + + public int getFSMstate() { + return FSMstate; + } + + protected void setFSMstate(int fSMstate) { + FSMstate = fSMstate; + } + + public void killSession(){ + log.warn("Killing Session"); + timer.cancel(); + this.endConnections(); + this.cancelDeadTimer(); + this.cancelKeepAlive(); + this.endSession(); + this.BGP4SessionsInformation.deleteSession(this.sessionId); + log.warn("Interrupting thread!!!!"); + this.interrupt(); + } + + /** + * DO HERE ANYTHING NEEDED AT CLOSING?? + * STATISTICS, ETC + */ + protected abstract void endSession(); + + protected void initializeBGP4Session() throws BGP4Exception { + this.BGP4SessionsInformation.addSession(this.getSessionId(), this); + + /** + * Byte array to store the last PCEP message read. + */ + byte[] msg = null; + //First get the input and output stream + try { + out = new DataOutputStream(socket.getOutputStream()); + in = new DataInputStream(socket.getInputStream()); + } catch (IOException e) { + log.warn("Problem in the sockets, ending BGP4Session"); + killSession(); + return; + } + //- Starts the ConnectRetryTimer with initial value + int initialValue=1000;//FIXME: no tengo ni idea de este parametro aun + connectRetryTimer= new ConnectRetryTimer(initialValue) ; + + //STARTING PCEP SESSION ESTABLISHMENT PHASE + //It begins in Open Wait State + this.setFSMstate(BGP4StateSession.BGP4_STATE_OPEN_WAIT); + log.debug("Entering BGP4_STATE_OPEN_WAIT, Scheduling Open Wait Timer"); + + //Create the 60 seconds Open Wait Timer to wait for an OPEN message + OpenWaitTimerTask owtt= new OpenWaitTimerTask(this); + this.timer.schedule(owtt, 60000); + //Define (Not use yet), the keepwait timer + KeepWaitTimerTask kwtt=new KeepWaitTimerTask(this); + BGP4Open open_msg=new BGP4Open(); + //Rellenar: + // - My autonomous system + // - holdTime + // - BGPIdentifier + open_msg.setMyAutonomousSystem(myAutonomousSystem); + open_msg.setBGPIdentifier(BGPIdentifier); + open_msg.setHoldTime(holdTime); + //Chek optional parameters + BGP4CapabilitiesOptionalParameter cop = new BGP4CapabilitiesOptionalParameter(); + open_msg.getParametersList().add(cop); + MultiprotocolExtensionCapabilityAdvertisement multProtExtCapAdv = new MultiprotocolExtensionCapabilityAdvertisement(); + multProtExtCapAdv.setAFI(AFICodes.AFI_BGP_LS); + multProtExtCapAdv.setSAFI(SAFICodes.SAFI_BGP_LS); + cop.getCapabilityList().add(multProtExtCapAdv); + BGP4OctetsASByteCapabilityAdvertisement fouroctects = new BGP4OctetsASByteCapabilityAdvertisement(); + fouroctects.setAS(myAutonomousSystem); + cop.getCapabilityList().add(fouroctects); + + //Send the OPEN message + this.sendBGP4Message(open_msg); + //Now, read messages until we are in SESSION UP + while (this.FSMstate!=BGP4StateSession.BGP4_STATE_SESSION_UP){ + //log.info("State session "+this.FSMstate); + try { + //Read a new message + msg = readBGP4Msg(in); + + }catch (IOException e){ + log.warn("Error reading message, ending session"+e.getMessage()); + killSession(); + return; + } + if (msg != null) {//If null, it is not a valid PCEP message + //log.info("Read a message"); + switch(BGP4Message.getMessageType(msg)) { + case BGP4MessageTypes.MESSAGE_OPEN: + //log.info("OPEN Message Received"); + if (this.FSMstate==BGP4StateSession.BGP4_STATE_OPEN_WAIT){ + log.debug("FSMstate = BGP4_STATE_OPEN_WAIT"); + BGP4Open open_received; + // try { + open_received=new BGP4Open(msg); + log.debug("**** Open received ****\n"+ open_received.toString());//FIXME!!! Cambiar a finest + owtt.cancel(); + //Check parameters + if (openRetry==1){ + boolean checkOK=true; + this.version = open_received.getVersion(); + if (this.version != 4){ + checkOK=false; + } + // this.deadTimerPeer=open_received.getDeadTimer(); + // this.keepAlivePeer=open_received.getKeepalive(); + // + // if (this.deadTimerPeer>maxDeadTimerAccepted){ + // checkOK=false; + // } + // if (this.deadTimerPeer==0){ + // if(zeroDeadTimerAccepted==false){ + // checkOK=false; + // } + // } + // if (this.keepAlivePeer perrobjlist=new LinkedList(); + // perrobjlist.add(perrorObject); + // perror.setErrorObjList(perrobjlist); + // perror.setOpen(open_received.getOpen()); + // log.info("Sending Error with new proposal"); + // this.sendPCEPMessage(perror); + // this.openRetry=this.openRetry+1; + /** + * o If LocalOK=1, the system restarts the OpenWait timer and stays in + the OpenWait state. + o If LocalOK=0, the system clears the OpenWait timer, starts the + KeepWait timer, and moves to the KeepWait state. + */ + if (localOK==true){ + //log.info("Local ok esta a true, vamos a open wait"); + owtt.cancel(); + owtt= new OpenWaitTimerTask(this); + this.timer.schedule(owtt, 60000); + this.setFSMstate(BGP4StateSession.BGP4_STATE_OPEN_WAIT); + } + else { + //log.info("Local ok esta a false, vamos a keep wait"); + owtt.cancel(); + this.setFSMstate(BGP4StateSession.BGP4_STATE_KEEP_WAIT); + this.timer.schedule(kwtt, 60000); + } + } + else { + /* + * If no errors are detected, and the session characteristics are + acceptable to the local system, the system: + o Sends a Keepalive message to the PCEP peer, + o Starts the Keepalive timer, + o Sets the RemoteOK variable to 1. + If LocalOK=1, the system clears the OpenWait timer and moves to the + UP state. + If LocalOK=0, the system clears the OpenWait timer, starts the + KeepWait timer, and moves to the KeepWait state. + */ + this.BGPIdentifier=open_received.getBGPIdentifier(); + this.myAutonomousSystem=open_received.getMyAutonomousSystem(); + this.holdTime=open_received.getHoldTime(); +// if (open_received.getOptionalParameterLength() != 0){ +// log.info("Tiene parametros opcionales"); +// } + //this.BGP4SessionsInformation.addSession(this.getSessionId(), this); + BGP4Keepalive p_ka= new BGP4Keepalive(); + //log.info("Sending Keepalive message"); + sendBGP4Message(p_ka); //Creates the Keep Wait Timer to wait for a KA to acknowledge the OPEN sent + //FIXME: START KA TIMER! + this.remoteOK=true; + if(this.localOK==true){ + //log.info("Entering STATE_SESSION_UP"); + //He conseguido establecer sesion. Hay que matar el otro hilo + + this.setFSMstate(BGP4StateSession.BGP4_STATE_SESSION_UP); + //La sesion se ha establecido + + } + else { + //log.info("Entering STATE_KEEP_WAIT"); + //log.fine("Scheduling KeepwaitTimer"); + timer.schedule(kwtt, 60000); + this.setFSMstate(BGP4StateSession.BGP4_STATE_KEEP_WAIT); + } + } + } + } + else{ + log.debug("Ignore OPEN message, already one received!!"); + } + + break; + case BGP4MessageTypes.MESSAGE_KEEPALIVE: + //log.info("KeepAlive Message Received"); + this.localOK=true; + if(this.FSMstate==BGP4StateSession.BGP4_STATE_KEEP_WAIT){ + // If RemoteOK=1, the system clears the KeepWait timer and moves to + // the UP state. + // If RemoteOK=0, the system clears the KeepWait timer, starts the + // OpenWait timer, and moves to the OpenWait State. + + if (remoteOK==true){ + kwtt.cancel(); + //log.info("Entering STATE_SESSION_UP"); + this.setFSMstate(BGP4StateSession.BGP4_STATE_SESSION_UP); + } + else{ + kwtt.cancel(); + //log.info("Entering OPEN WAIT STATE"); + owtt=new OpenWaitTimerTask(this); + this.timer.schedule(owtt, 60000); + this.setFSMstate(BGP4StateSession.BGP4_STATE_OPEN_WAIT); + } + + } + //If not... seguimos igual que estabamos + //Mas KA no hacen mal... + break; + + default: + log.error("UNEXPECTED Message Received"); + if (this.FSMstate!=BGP4StateSession.BGP4_STATE_OPEN_WAIT){ + log.debug("Ignore OPEN message, already one received!!"); + } + else { + log.error("Unexpected message RECEIVED, closing"); + + } + break; + } + } + else { + if (this.FSMstate!=BGP4StateSession.BGP4_STATE_OPEN_WAIT){ + log.info("Ignore message, already one received!!"); + } + else { + log.error("Unexpected message RECEIVED, closing"); + + } + }//Fin del else + }//Fin del WHILE + } + + + @Override + public void sendBGP4Message(BGP4Message message) { + message.encode(); + try { + out.write(message.getBytes()); + out.flush(); + } catch (Exception e) { + log.error("Problem writing message, finishing session "+e.getMessage()); + killSession(); + } + + } + + + public Inet4Address getRemotePeerIP() { + return remotePeerIP; + } + + + public Inet4Address getBGPIdentifier() { + return BGPIdentifier; + } + + public void setBGPIdentifier(Inet4Address bGPIdentifier) { + BGPIdentifier = bGPIdentifier; + } + + public Boolean getUpdateFrom() { + return updateFrom; + } + + public void setUpdateFrom(Boolean updateFrom) { + this.updateFrom = updateFrom; + } + + public Boolean getSendTo(){ + return sendTo; + } + + public void setSendTo(boolean sendTo) { + this.sendTo = sendTo; + } + + public int getMyAutonomousSystem() { + return myAutonomousSystem; + } + + public void setMyAutonomousSystem(int myAutonomousSystem) { + this.myAutonomousSystem = myAutonomousSystem; + } + + + + public String shortInfo(){ + StringBuffer sb=new StringBuffer(1000); + if (this.socket!=null){ + sb.append("remAddr: "); + sb.append(this.socket.getRemoteSocketAddress()); + sb.append(" state: "); + if (this.FSMstate==BGP4StateSession.BGP4_STATE_OPEN_WAIT){ + sb.append("OPEN_WAIT"); + }else if (this.FSMstate==BGP4StateSession.BGP4_STATE_IDLE){ + sb.append("IDLE"); + }else if (this.FSMstate==BGP4StateSession.BGP4_STATE_KEEP_WAIT){ + sb.append("KEEP_WAIT"); + }else if (this.FSMstate==BGP4StateSession.BGP4_STATE_SESSION_UP){ + sb.append("SESSION_UP"); + }else if (this.FSMstate==BGP4StateSession.BGP4_STATE_SESSION_UP){ + sb.append("TCP_PENDING"); + }else { + sb.append("UNKNOWN"); + } + + } + + return sb.toString(); + } + + public String toString(){ + StringBuffer sb=new StringBuffer(1000); + sb.append("\t> Session ID: "+this.sessionId+"\n"); + sb.append("\t> BGP Remote Peer: "+this.remotePeerIP+"\n"); + sb.append("\t> BGPIdentifier: "+this.BGPIdentifier+"\n"); + if (this.socket!=null){ + sb.append("\t> remAddr: "); + sb.append(this.socket.getRemoteSocketAddress()+"\n"); + sb.append("\t> state: "); + if (this.FSMstate==BGP4StateSession.BGP4_STATE_OPEN_WAIT){ + sb.append("OPEN_WAIT\n"); + }else if (this.FSMstate==BGP4StateSession.BGP4_STATE_IDLE){ + sb.append("IDLE\n"); + }else if (this.FSMstate==BGP4StateSession.BGP4_STATE_KEEP_WAIT){ + sb.append("KEEP_WAIT\n"); + }else if (this.FSMstate==BGP4StateSession.BGP4_STATE_SESSION_UP){ + sb.append("SESSION_UP\n"); + }else if (this.FSMstate==BGP4StateSession.BGP4_STATE_SESSION_UP){ + sb.append("TCP_PENDING\n"); + }else { + sb.append("UNKNOWN"); + } + } + + return sb.toString(); + } + + public synchronized void newSessionId(){ + this.sessionId=GenericBGP4Session.sessionIdCounter+1; + sessionIdCounter=sessionIdCounter+1; + } + + public long getSessionId() { + return sessionId; + } + + + @Override + public void close() { + // TODO Auto-generated method stub + + } + + @Override + public boolean equals(Object obj) { + if (remotePeerIP != null){ + if (this.remotePeerIP.equals(((GenericBGP4Session)obj).getBGPIdentifier())){ + return true; + } + } + else { + log.info("TODO NUL!! en el equals!"); + } + return false; + } + + + public Inet4Address getPeerIP(){ + return (Inet4Address)this.socket.getInetAddress(); + } +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/KeepAliveThread.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/KeepAliveThread.java new file mode 100644 index 000000000..70ebe101f --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/KeepAliveThread.java @@ -0,0 +1,98 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.bgp4session; +import es.tid.bgp.bgp4.messages.BGP4Keepalive; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.DataOutputStream; +import java.io.IOException; + + +public class KeepAliveThread extends Thread { + + private int keepAlive = 0; + private boolean running; + private Logger log; + private DataOutputStream out=null; //Use this to send messages to peer + + /* + * @param p + * @param k + */ + public KeepAliveThread(DataOutputStream out, int k) { + this.keepAlive = k; + this.out = out; + log=LoggerFactory.getLogger("BGP4Server"); + } + + /** + * Starts the Keepalive process + */ + public void run() { + running=true; + while (running) { + try { + if (keepAlive > 0) { + sleep(keepAlive * 1000); + sendKeepAlive(); + } + else { + log.debug("Ending KEEPALIVE mechanism"); + return; + } + } catch (InterruptedException e) { + if (running==false){ + log.debug("Ending KeepAliveThread"); + return; + } + else { + //Keepalive Timer is reseted + log.debug("Reseting Keepalive timer"); + } + } + } + } + + /** + * Sets the running variable to false. After this, an interrupt will cause + * the KeepaliveThread to end. + */ + public void stopRunning(){ + running=false; + } + /** + * Sends KeepAlive Message. It does not wait for any response. + */ + private void sendKeepAlive() { + BGP4Keepalive p_ka= new BGP4Keepalive(); + //try { + p_ka.encode(); +// } catch (PCEPProtocolViolationException e1) { +// // TODO Auto-generated catch block +// e1.printStackTrace(); +// } + try { + log.debug("Sending Keepalive message"); + out.write(p_ka.getBytes()); + out.flush(); + } catch (IOException e) { + log.warn("Error sending KEEPALIVE: " + e.getMessage()); + } + } + + } + + diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/KeepWaitTimerTask.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/KeepWaitTimerTask.java new file mode 100644 index 000000000..3bc72c84d --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/KeepWaitTimerTask.java @@ -0,0 +1,58 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.bgp4session; + + +import java.util.TimerTask; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * If no Open message is received before the expiration of the OpenWait + timer, the PCEP peer sends a PCErr message with Error-Type=1 and + Error-value=2, the system releases the PCEP resources for the PCEP + peer, closes the TCP connection, and moves to the Idle state. + + * @author Oscar Gonzalez de Dios + * + */ +public class KeepWaitTimerTask extends TimerTask { + +// private DataOutputStream out=null; //Use this to send messages to peer + private BGP4Session bgp4Session; + private Logger log; + + public KeepWaitTimerTask(BGP4Session bgp4Session){ + this.bgp4Session=bgp4Session; + log=LoggerFactory.getLogger("PCEServer"); + } + + + public void run() { + log.warn("KEEP WAIT Timer OVER"); +// PCEPError perror=new PCEPError(); +// PCEPErrorObject perrorObject=new PCEPErrorObject(); +// perrorObject.setErrorType(ObjectParameters.ERROR_ESTABLISHMENT); +// perrorObject.setErrorValue(ObjectParameters.ERROR_ESTABLISHMENT_NO_KA_OR_ERROR_KEEPWAIT_TIMER); +// ErrorConstruct error_c=new ErrorConstruct(); +// error_c.getErrorObjList().add(perrorObject); +// perror.setError(error_c); +// bgp4Session.sendBGP4Message(perror); + this.bgp4Session.killSession(); + return; + } + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/OpenWaitTimerTask.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/OpenWaitTimerTask.java new file mode 100644 index 000000000..20b77ce4e --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/bgp4session/OpenWaitTimerTask.java @@ -0,0 +1,59 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.bgp4session; + +import java.util.TimerTask; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + + +/** + * If no Open message is received before the expiration of the OpenWait + timer, the PCEP peer sends a PCErr message with Error-Type=1 and + Error-value=2, the system releases the PCEP resources for the PCEP + peer, closes the TCP connection, and moves to the Idle state. + + * @author Oscar Gonzalez de Dios + * + */ +public class OpenWaitTimerTask extends TimerTask { + +// private DataOutputStream out=null; //Use this to send messages to peer + private BGP4Session bgp4Session; + private Logger log; + + public OpenWaitTimerTask(BGP4Session bgp4Session){ + this.bgp4Session=bgp4Session; + log=LoggerFactory.getLogger("PCEServer"); + } + + + public void run() { + log.warn("OPEN WAIT Timer OVER"); +// PCEPError perror=new PCEPError(); +// PCEPErrorObject perrorObject=new PCEPErrorObject(); +// perrorObject.setErrorType(ObjectParameters.ERROR_ESTABLISHMENT); +// perrorObject.setErrorValue(ObjectParameters.ERROR_ESTABLISHMENT_NO_OPEN_MESSAGE); +// ErrorConstruct error_c=new ErrorConstruct(); +// error_c.getErrorObjList().add(perrorObject); +// perror.setError(error_c); +// log.info("Sending Error"); +// bgp4Session.sendPCEPMessage(perror); + this.bgp4Session.killSession(); + return; + } + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/grpcApp.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/grpcApp.java new file mode 100644 index 000000000..329404668 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/grpcApp.java @@ -0,0 +1,38 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.grpc; + +import io.grpc.Server; +import io.grpc.ServerBuilder; + +public class grpcApp { + + public static void main( String[] args ) throws Exception + { + // Create a new server to listen on port 8080 + Server server = ServerBuilder.forPort(2021) + .addService(new updateServiceImpl()) + .build(); + + // Start the server + server.start(); + + // Server threads are running in the background. + System.out.println("Server started"); + // Don't exit the main thread. Wait until server is terminated. + server.awaitTermination(); + } + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/grpcClient.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/grpcClient.java new file mode 100644 index 000000000..6e74dff00 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/grpcClient.java @@ -0,0 +1,368 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.grpc; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import com.google.common.net.InetAddresses; + +import eu.teraflow.tid.bgp4Peer.models.LinkNLRIMsg; +import eu.teraflow.tid.bgp4Peer.models.NodeNLRIMsg; +import eu.teraflow.tid.bgp4Peer.models.UpdateMsg; +import eu.teraflow.tid.bgp4Peer.models.UpdateMsgList; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import io.grpc.stub.StreamObserver; +import jdk.javadoc.internal.doclets.toolkit.util.links.LinkInfo; +import src.main.proto.GrpcService.linkInfo; +import src.main.proto.GrpcService.nodeInfo; +import src.main.proto.GrpcService.NodeDescriptors; +import src.main.proto.GrpcService.updateRequest; +import src.main.proto.GrpcService.updateResponse; +import src.main.proto.updateServiceGrpc; +import src.main.proto.updateServiceGrpc.updateServiceBlockingStub; +import src.main.proto.updateServiceGrpc.updateServiceStub; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; + +public class grpcClient { + + private static final Logger logger = Logger.getLogger(grpcClient.class.getName()); + + public static void sendGrpcUpdateMsg(UpdateMsg update) throws Exception{ + + updateRequest request=null; + nodeInfo n=null; + linkInfo unic=null; + List l = new ArrayList<>(); + List nodes = new ArrayList<>(); + if(update.nodeCheck()==false && update.linkCheck()==false){ + return; + } +// Build node for grpc message + if(update.nodeCheck()!=false) { + for(NodeNLRIMsg node : update.getNodeList()){ + n = nodeInfo.newBuilder().setNodeName(node.getNodeName()). + setIgpID(node.getRouterID()). + setBgplsID(node.getLocalBgplsID()). + setAsID(InetAddresses.coerceToInteger(node.getAs_number())). + setLearntFrom(node.getLearntFrom()). + buildPartial(); + nodes.add(n); + } + } + for(LinkNLRIMsg link : update.getLinkList()) { + +// String strIPlocal; +// String strIPremote; + String strIgpR; + String strIgpL; + // LinkNLRIMsg link=update.getLink(); + +// if(link.getiPv4RouterIDLocalNodeLATLV()==null) +// strIPlocal="-"; +// else { +// strIPlocal=link.getiPv4RouterIDLocalNodeLATLV(); +// } +// if(link.getiPv4RouterIDNeighborNodeLATLV()==null) +// strIPremote="-"; +// else { +// strIPremote=link.getiPv4RouterIDNeighborNodeLATLV(); +// } + + if(link.getRemoteNodeIGPId()==null) + strIgpR="-"; + else { + strIgpR=link.getRemoteNodeIGPId().toString(); + } + if(link.getLocalNodeIGPId()==null) + strIgpL="-"; + else { + strIgpL=link.getLocalNodeIGPId().toString(); + } + String ipv4R; + if(link.getiPv4RouterIDLocalNodeLATLV()==null) + ipv4R="-"; + else { + ipv4R=link.getiPv4RouterIDLocalNodeLATLV(); + } + String ipv4L; + if(link.getiPv4RouterIDNeighborNodeLATLV()==null) + ipv4L="-"; + else { + ipv4L=link.getiPv4RouterIDNeighborNodeLATLV(); + } + +// Build link for grpc message. need non null values in some cases + + unic = linkInfo.newBuilder().setLocalID(strIgpR). + setLocalIPv4ID(ipv4L). + setRemoteID(strIgpL). + setRemoteIPv4ID(ipv4R). + setLocal(NodeDescriptors.newBuilder(). + setAsNumber(link.getLocalDomainID().toString()). + setBgplsID(link.getLocalBgplsID())). + setRemote(NodeDescriptors.newBuilder(). + setAsNumber(link.getRemoteDomainID().toString()). + setBgplsID(link.getRemoteBgplsID())). + setAvailableBw(link.getAvailableBw()). + setResidualBw(link.getResidualBw()).setUtilized(link.getUtilizedBw()). + setMinLinkDelay(link.getMinDelay()).setMaxLinkDelay(link.getMaxDelay()). + setDelayVariation(link.getLinkDelayVar()).setDelay(link.getLinkDelay()). + setTEDefaultMetric(1).setAdjacencySid("0").setLearntFrom(link.getLearntFrom()).buildPartial(); + + l.add(unic); + } + + if(nodes.size()==0 && l.size()>0) { + request=updateRequest.newBuilder(). + setNextHop(update.getNextHop().toString()). + setAddressFamilyID(Integer.toString(update.getAFI())). + setAsPathSegment(Integer.toString(update.getAsPathSegment())). + addAllLink(l).build(); + }else if(nodes.size()>0&& l.size()==0) { + // logger.debug("ADDING NODE"); + request=updateRequest.newBuilder(). + setNextHop(update.getNextHop().toString()). + setAddressFamilyID(Integer.toString(update.getAFI())). + setAsPathSegment(Integer.toString(update.getAsPathSegment())). + addAllNode(nodes).build(); + }else { + //Error if node name is null + // TODO: handle seng grpc error? + // logger.debug("ADDING NODE AND LINK"); + request=updateRequest.newBuilder(). + setNextHop("-"+update.getNextHop().toString()). + setAddressFamilyID(Integer.toString(update.getAFI())). + setAsPathSegment(Integer.toString(update.getAsPathSegment())). + addAllNode(nodes).addAllLink(l).build(); + + } + final ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost",2021).usePlaintext().build(); + updateServiceBlockingStub stub = updateServiceGrpc.newBlockingStub(channel); + + //TODO: this to a function + System.out.println("grpcClient request: "+request.toString()); + + // channel.awaitTermination(20, TimeUnit.SECONDS); + // updateResponse response = stub.update(request); + // Espera hasta que el canal esté inactivo + updateResponse response = stub.update(request); + + System.out.println("\nRESPUESTA RECIBIDA"); + System.out.println(response); + } + // private void shutdownManagedChannel(ManagedChannel managedChannel) { + // managedChannel.shutdown(); + // try { + // managedChannel.awaitTermination(mChannelShutdownTimeoutMs, TimeUnit.MILLISECONDS); + // } catch (InterruptedException e) { + // Thread.currentThread().interrupt(); + // // Allow thread to exit. + // } finally { + // managedChannel.shutdownNow(); + // } + // Verify.verify(managedChannel.isShutdown()); + // } + // stub.update(request, new StreamObserver () { + + // public void onNext(updateResponse response) { + // System.out.println("respuesta del server: "+response); + // } + // public void onError(Throwable t) { + // System.out.println("error: "+t.getMessage()); + // latch.countDown(); + // } + // public void onCompleted() { + // // Typically you'll shutdown the channel somewhere else. + // // But for the purpose of the lab, we are only making a single + // // request. We'll shutdown as soon as this request is done. + // latch.countDown(); + // logger.info("gRPC call completed"); + // System.out.println("OnCompleted"); + // // channel.shutdownNow(); + // // try{ + // // channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); + // // }catch (InterruptedException e){ + // // System.out.println("channel error"+e.toString()); + // // } + + // } + // }); + // latch.await(5, TimeUnit.SECONDS); + // channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); + + public static void sendGrpc(UpdateMsgList update) { + //construir mensaje + //update get node,lin,path + //getname,ids,as + final ManagedChannel channel = ManagedChannelBuilder.forTarget("localhost:2021").usePlaintext().build(); + updateServiceStub stub = updateServiceGrpc.newStub(channel); + + + if(update.getNodeList().isEmpty()&&update.getLinkList().isEmpty()) { + return; + } + updateRequest request=null; + nodeInfo n=null; + linkInfo l=null; + if(!update.getNodeList().isEmpty()) { + + for(NodeNLRIMsg node: update.getNodeList()) { + + n = nodeInfo.newBuilder().setNodeName(node.getNodeName()).setIgpID(node.getLocalBgplsID()). + setBgplsID(node.getBgplsID().toString()).setAsID(InetAddresses.coerceToInteger(node.getAs_number())). + buildPartial(); + } + + + } + if(!update.getLinkList().isEmpty()) { + + String strIPlocal; + String strIPremote; + String strIgpR; + String strIgpL; + + for(LinkNLRIMsg link: update.getLinkList()) { + + if(link.getiPv4RouterIDLocalNodeLATLV()==null) + strIPlocal="-"; + else { + strIPlocal=link.getiPv4RouterIDLocalNodeLATLV(); + } + if(link.getiPv4RouterIDNeighborNodeLATLV()==null) + strIPremote="-"; + else { + strIPremote=link.getiPv4RouterIDNeighborNodeLATLV(); + } + + if(link.getRemoteNodeIGPId()==null) + strIgpR="-"; + else { + strIgpR=link.getRemoteNodeIGPId().toString(); + } + if(link.getLocalNodeIGPId()==null) + strIgpL="-"; + else { + strIgpL=link.getLocalNodeIGPId().toString(); + } + String ipv4R; + if(link.getiPv4RouterIDNeighborNodeLATLV()==null) + ipv4R="-"; + else { + ipv4R=link.getiPv4RouterIDNeighborNodeLATLV(); + } + String ipv4L; + if(link.getiPv4RouterIDLocalNodeLATLV()==null) + ipv4L="-"; + else { + ipv4L=link.getiPv4RouterIDLocalNodeLATLV(); + } + +// NodeDescriptors local= NodeDescriptors.newBuilder(). +// setAsNumber(link.getLocalDomainID().toString()). +// setBgplsID(link.getLocalBgplsID()).buildPartial(); + + + l = linkInfo.newBuilder().setLocalID(strIgpR). + setLocalIPv4ID(ipv4L). + setRemoteID(strIgpL). + setRemoteIPv4ID(ipv4R). + setLocal(NodeDescriptors.newBuilder(). + setAsNumber(link.getLocalDomainID().toString()). + setBgplsID(link.getLocalBgplsID())). + setRemote(NodeDescriptors.newBuilder(). + setAsNumber(link.getRemoteDomainID().toString()). + setBgplsID(link.getRemoteBgplsID())). + setAvailableBw(link.getAvailableBw()). + setResidualBw(link.getResidualBw()).setUtilized(link.getUtilizedBw()). + setMinLinkDelay(link.getMinDelay()).setMaxLinkDelay(link.getMaxDelay()). + setDelayVariation(link.getLinkDelayVar()).setDelay(link.getLinkDelay()). + setTEDefaultMetric(1).setAdjacencySid("0").buildPartial(); + } + + } + if(n==null) { + request = updateRequest.newBuilder().addLink(l).build(); + }else if(l==null) { + request = updateRequest.newBuilder().addNode(n).build(); + }else { + request = updateRequest.newBuilder().addNode(n).addLink(l).build(); + } + + + + + + stub.update(request, new StreamObserver () { + + public void onNext(updateResponse response) { + System.out.println("respuesta del server: "+response); + } + public void onError(Throwable t) { + System.out.println("error: "+t.getMessage()); + } + public void onCompleted() { + // Typically you'll shutdown the channel somewhere else. + // But for the purpose of the lab, we are only making a single + // request. We'll shutdown as soon as this request is done. + System.out.println("channel shutdown"); + channel.shutdownNow(); + } + }); + + + + + + } + public static void main( String[] args ) throws Exception + { + final ManagedChannel channel = ManagedChannelBuilder.forTarget("localhost:2021").usePlaintext().build(); + + // Replace the previous synchronous code with asynchronous code. + // This time use an async stub: + updateServiceStub stub = updateServiceGrpc.newStub(channel); + + // Construct a request + int a = 123; + nodeInfo n = nodeInfo.newBuilder().setNodeName("router 3").setIgpID("1341234").buildPartial(); + updateRequest request = + updateRequest.newBuilder().addNode(n).build(); + + // Make an Asynchronous call. Listen to responses w/ StreamObserver + stub.update(request, new StreamObserver () { + + public void onNext(updateResponse response) { + System.out.println("respuesta del server: "+response); + } + public void onError(Throwable t) { + System.out.println("error: "+t.getMessage()); + } + public void onCompleted() { + // Typically you'll shutdown the channel somewhere else. + // But for the purpose of the lab, we are only making a single + // request. We'll shutdown as soon as this request is done. + System.out.println("channel shutdown"); + channel.shutdownNow(); + } + }); + } +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/updateServiceImpl.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/updateServiceImpl.java new file mode 100644 index 000000000..3010cbbfb --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/grpc/updateServiceImpl.java @@ -0,0 +1,42 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.grpc; + +import io.grpc.stub.StreamObserver; +import src.main.proto.GrpcService.updateRequest; +import src.main.proto.GrpcService.updateResponse; +import src.main.proto.updateServiceGrpc.updateServiceImplBase; + + +public class updateServiceImpl extends updateServiceImplBase{ + +public void update(updateRequest request, StreamObserver responseObserver) { + + System.out.println(request); + + updateResponse response = updateResponse.newBuilder() + .setAck("Update procesado, " + request ) + .build(); + + // Use responseObserver to send a single response back + responseObserver.onNext(response); + + + // When you are done, you must call onCompleted. + responseObserver.onCompleted(); + + } + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/json/bgpMarshal.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/json/bgpMarshal.java new file mode 100644 index 000000000..87d141222 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/json/bgpMarshal.java @@ -0,0 +1,82 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.json; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +import org.codehaus.jackson.JsonEncoding; +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; + +import eu.teraflow.tid.bgp4Peer.models.LinkNLRIMsg; +import eu.teraflow.tid.bgp4Peer.models.NodeNLRIMsg; +import eu.teraflow.tid.bgp4Peer.models.PathAttributeMsg; +import eu.teraflow.tid.bgp4Peer.models.UpdateMsg; +import eu.teraflow.tid.bgp4Peer.models.UpdateMsgList; + +public class bgpMarshal { + + + ObjectMapper mapper = new ObjectMapper(); + JsonGenerator g; + FileWriter fWriter; + public void bgpMarshaller() throws IOException{ + + + mapper.setSerializationInclusion(Inclusion.NON_NULL); + mapper.setSerializationInclusion(Inclusion.NON_EMPTY); + + + +// String jsonStr = mapper.writeValueAsString(node); +// mapper.writeValue(new File("target/node.json"), nodeList); +// System.out.println(jsonStr); + + } + public void writeFile(UpdateMsgList update) throws JsonGenerationException, JsonMappingException, IOException { + + g = mapper.getJsonFactory().createJsonGenerator(new File("node.json"), JsonEncoding.UTF8); +// update=update.id2Name(); + mapper.writeValue(g, update); + String temp = mapper.writeValueAsString(update)+"\n"; +// FileOutputStream fos = new FileOutputStream("target/update.json", true); +// fos.write(temp.getBytes()); +// fos.close(); + fWriter = new FileWriter("updateWriter.json"); +// if(temp.length()>2) + fWriter.write(temp); + + + + } + public void closeFile() throws IOException { + g.close(); + fWriter.close(); + } + + + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/management/BGP4ManagementServer.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/management/BGP4ManagementServer.java new file mode 100644 index 000000000..f135a446d --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/management/BGP4ManagementServer.java @@ -0,0 +1,85 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.management; + +import eu.teraflow.tid.bgp4Peer.bgp4session.BGP4SessionsInformation; +import eu.teraflow.tid.bgp4Peer.peer.SendTopology; +import eu.teraflow.tid.tedb.MultiDomainTEDB; +import eu.teraflow.tid.tedb.TEDB; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.ServerSocket; +import java.util.Hashtable; +/** + * To manage the server + * + * @author mcs + * + */ +public class BGP4ManagementServer extends Thread { + private Logger log; + private int BGP4ManagementPort = 8888; + private BGP4SessionsInformation bgp4SessionsInformation; + /** + * Topology database for interDomain Links. + */ + private MultiDomainTEDB multiTEDB; + /** + * Topology database for intradomain Links. It owns several domains. + */ + private Hashtable intraTEDBs; + + /** + * Class to send the topology. It is needes to set the parameters sendTopology to true or false. + */ + private SendTopology sendTopology; + + public BGP4ManagementServer(int BGP4ManagementPort, MultiDomainTEDB multiTEDB, Hashtable intraTEDBs, BGP4SessionsInformation bgp4SessionsInformation, SendTopology sendTopology){ + log =LoggerFactory.getLogger("BGP4Server"); + this.BGP4ManagementPort = BGP4ManagementPort; + this.multiTEDB=multiTEDB; + this.intraTEDBs=intraTEDBs; + this.bgp4SessionsInformation =bgp4SessionsInformation; + this.sendTopology=sendTopology; + + } + /** + * RUN + */ + public void run(){ + ServerSocket serverSocket = null; + boolean listening=true; + try { + log.debug("Listening management on port "+BGP4ManagementPort); + serverSocket = new ServerSocket(BGP4ManagementPort); + } + catch (Exception e){ + log.error("Could not listen management on port "+BGP4ManagementPort); + e.printStackTrace(); + return; + } + + try { + while (listening) { + new BGP4ManagementSession(serverSocket.accept(),multiTEDB,intraTEDBs,bgp4SessionsInformation, sendTopology).start(); + } + serverSocket.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/management/BGP4ManagementSession.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/management/BGP4ManagementSession.java new file mode 100644 index 000000000..18a433e40 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/management/BGP4ManagementSession.java @@ -0,0 +1,199 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.management; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.net.Inet4Address; +import java.net.Socket; +import java.util.Enumeration; +import java.util.Hashtable; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import eu.teraflow.tid.bgp4Peer.bgp4session.BGP4SessionsInformation; +import eu.teraflow.tid.bgp4Peer.peer.SendTopology; +import eu.teraflow.tid.bgp4Peer.tedb.IntraTEDBS; +import eu.teraflow.tid.tedb.DomainTEDB; +import eu.teraflow.tid.tedb.MultiDomainTEDB; +import eu.teraflow.tid.tedb.SimpleTEDB; +import eu.teraflow.tid.tedb.TEDB; + +/** + * + * @author mcs + * + */ +public class BGP4ManagementSession extends Thread { + /** + * The socket of the management session + */ + private Socket socket; + + /** + * Logger + */ + private Logger log; + + /** + * Output Stream of the managament session, to write the answers. + */ + private PrintStream out; + /** + * Topology database for interDomain Links. + */ + private MultiDomainTEDB multiTEDB; + /** + * Topology database for intradomain Links. It owns several domains. + */ + private Hashtable intraTEDBs; + + /** + * The infomation of all the active sessions + */ + private BGP4SessionsInformation bgp4SessionsInformation; + /** + * Class to send the topology. It is needes to set the parameters sendTopology to true or false. + */ + private SendTopology sendTopology; + + public BGP4ManagementSession(Socket s,MultiDomainTEDB multiTEDB, Hashtable intraTEDBs,BGP4SessionsInformation bgp4SessionsInformation, SendTopology sendTopology){ + this.socket=s; + log=LoggerFactory.getLogger("BGP4Server"); + this.multiTEDB=multiTEDB; + this.intraTEDBs=intraTEDBs; + this.bgp4SessionsInformation= bgp4SessionsInformation; + this.sendTopology=sendTopology; + } + + public void run(){ + log.info("Starting Management session"); + boolean running=true; + try { + out=new PrintStream(socket.getOutputStream()); + } catch (IOException e) { + log.warn("Management session cancelled: "+e.getMessage()); + return; + } + try { + BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); + while (running) { + //out.print("BGP4:>"); + + + + out.print("Available commands:\r\n"); + out.print(" > show topology\r\n"); + out.print(" > show sessions\r\n"); + out.print(" > set traces on\r\n"); + out.print(" > set traces off\r\n"); + out.print(" > send topology on\r\n"); + out.print(" > send topology off\r\n"); + out.print(" > quit\r\n"); + + + String command = null; + try { + command = br.readLine(); + } catch (IOException ioe) { + log.warn("IO error trying to read your command"); + return; + } + if (command.equals("quit")) { + log.info("Ending Management Session"); + out.println("bye!"); + try { + out.close(); + } catch (Exception e){ + e.printStackTrace(); + } + try { + br.close(); + } catch (Exception e){ + e.printStackTrace(); + } + return; + } + +// else if (command.equals("help")){ +// out.print("Available commands:\r\n"); +// out.print(" > show topology\r\n"); +// out.print(" > show sessions\r\n"); +// out.print(" > set traces on\r\n"); +// out.print(" > set traces off\r\n"); +// out.print(" > send topology on\r\n"); +// out.print(" > send topology off\r\n"); +// out.print(" > quit\r\n"); +// +// } + else if (command.equals("show sessions")){ + //Print intradomain and interDomain links + out.print(bgp4SessionsInformation.toString()); + } + else if (command.equals("show topology")){ + //Print intradomain and interDomain links + if (multiTEDB != null) + out.println(multiTEDB.printTopology()); + Enumeration domainTedbs=intraTEDBs.keys(); + while (domainTedbs.hasMoreElements()){ + String domainID=domainTedbs.nextElement(); + TEDB ted=intraTEDBs.get(domainID); + if (ted instanceof DomainTEDB) { + out.println("Intradomain TEDB with ID "+domainID); + out.println(ted.printTopology()); + } + + } + + } + else if (command.equals("set traces on")) { + //log.setLevel(Level.ALL); + Logger log2=LoggerFactory.getLogger("BGP4Parser"); + //log2.setLevel(Level.ALL); + Logger log3=LoggerFactory.getLogger("BGP4Client"); + //log3.setLevel(Level.ALL); + out.print("traces on!\r\n"); + } + else if (command.equals("set traces off")) { + //log.setLevel(Level.SEVERE); + Logger log2=LoggerFactory.getLogger("BGP4Parser"); + //log2.setLevel(Level.SEVERE); + Logger log3=LoggerFactory.getLogger("BGP4Client"); + //log3.setLevel(Level.SEVERE); + out.print("traces off!\r\n"); + } + else if (command.equals("send topology on")) { + sendTopology.setSendTopology(true); + } + else if (command.equals("send topology off")) { + sendTopology.setSendTopology(false); + } + else{ + out.print("invalid command\n"); + out.print("\n"); + } + + } + } catch (Exception e) { + e.printStackTrace(); + return; + } + } +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/LinkNLRIMsg.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/LinkNLRIMsg.java new file mode 100644 index 000000000..9455ccd1c --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/LinkNLRIMsg.java @@ -0,0 +1,298 @@ + +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.models; + +import java.net.Inet4Address; +import java.util.ArrayList; + +import org.slf4j.Logger; + +import es.tid.bgp.bgp4.update.fields.LinkNLRI; +import es.tid.bgp.bgp4.update.tlv.node_link_prefix_descriptor_subTLVs.NodeDescriptorsSubTLV; + +public class LinkNLRIMsg { + + private ArrayList nodeDescriptorsSubTLV; + // Dominios + private Inet4Address localDomainID; + private Inet4Address remoteDomainID; + + private Inet4Address areaID; + private Inet4Address bgplsID; + + private Inet4Address LocalNodeIGPId; + private Inet4Address RemoteNodeIGPId; + + private int linkDelay; + private int linkDelayVar; + private int minDelay; + private int maxDelay; + private int linkLoss; + private int residualBw; + private int availableBw; + private int utilizedBw; + + private Inet4Address iPv4RouterIDLocalNodeLATLV; + private Inet4Address iPv4RouterIDNeighborNodeLATLV; + + private int IGP_type; + private String localIGPID = null; + private String remoteIGPID = null; + private String localBgplsID; + private String remoteBgplsID; + private Logger log; + private String learntFrom; + + public LinkNLRIMsg(LinkNLRI linkNLRI, String learntFrom) { + + // LinkState vs Link?? + this.learntFrom = learntFrom; + + if (linkNLRI.getLocalNodeDescriptors().getAutonomousSystemSubTLV() != null) { + localDomainID = linkNLRI.getLocalNodeDescriptors().getAutonomousSystemSubTLV().getAS_ID(); + } + if (linkNLRI.getLocalNodeDescriptors().getAreaID() != null) { + areaID = linkNLRI.getLocalNodeDescriptors().getAreaID().getAREA_ID(); + } + if (linkNLRI.getLocalNodeDescriptors().getBGPLSIDSubTLV() != null) { + bgplsID = linkNLRI.getLocalNodeDescriptors().getBGPLSIDSubTLV().getBGPLS_ID(); + } + if (linkNLRI.getLocalNodeDescriptors().getIGPRouterID() != null) { + LocalNodeIGPId = linkNLRI.getLocalNodeDescriptors().getIGPRouterID().getIpv4AddressOSPF(); + } + + if (linkNLRI.getRemoteNodeDescriptorsTLV().getAutonomousSystemSubTLV() != null) { + remoteDomainID = linkNLRI.getRemoteNodeDescriptorsTLV().getAutonomousSystemSubTLV().getAS_ID(); + } + if (linkNLRI.getRemoteNodeDescriptorsTLV().getAreaID() != null) { + areaID = linkNLRI.getRemoteNodeDescriptorsTLV().getAreaID().getAREA_ID(); + } + if (linkNLRI.getRemoteNodeDescriptorsTLV().getBGPLSIDSubTLV() != null) { + bgplsID = linkNLRI.getRemoteNodeDescriptorsTLV().getBGPLSIDSubTLV().getBGPLS_ID(); + } + if (linkNLRI.getRemoteNodeDescriptorsTLV().getIGPRouterID() != null) { + RemoteNodeIGPId = linkNLRI.getRemoteNodeDescriptorsTLV().getIGPRouterID().getIpv4AddressOSPF(); + } + if (linkNLRI.getUndirectionalLinkDelayTLV() != null) { + linkDelay = linkNLRI.getUndirectionalLinkDelayTLV().getDelay(); + } + if (linkNLRI.getUndirectionalDelayVariationTLV() != null) { + linkDelayVar = linkNLRI.getUndirectionalDelayVariationTLV().getDelayVar(); + } + if (linkNLRI.getMinMaxUndirectionalLinkDelayTLV() != null) { + maxDelay = linkNLRI.getMinMaxUndirectionalLinkDelayTLV().getHighDelay(); + minDelay = linkNLRI.getMinMaxUndirectionalLinkDelayTLV().getLowDelay(); + } + if (linkNLRI.getUndirectionalLinkLossTLV() != null) { + linkLoss = linkNLRI.getUndirectionalLinkLossTLV().getLinkLoss(); + } + if (linkNLRI.getUndirectionalResidualBwTLV() != null) { + residualBw = linkNLRI.getUndirectionalResidualBwTLV().getResidualBw(); + } + if (linkNLRI.getUndirectionalAvailableBwTLV() != null) { + availableBw = linkNLRI.getUndirectionalAvailableBwTLV().getAvailableBw(); + } + if (linkNLRI.getUndirectionalUtilizedBwTLV() != null) { + utilizedBw = linkNLRI.getUndirectionalUtilizedBwTLV().getUtilizedBw(); + } + if (linkNLRI.getIpv4InterfaceAddressTLV() != null) { + iPv4RouterIDLocalNodeLATLV = linkNLRI.getIpv4InterfaceAddressTLV().getIpv4Address(); + } + if (linkNLRI.getIpv4NeighborAddressTLV() != null) { + iPv4RouterIDNeighborNodeLATLV = linkNLRI.getIpv4NeighborAddressTLV().getIpv4Address(); + } + if (linkNLRI.getLocalNodeDescriptors().getBGPLSIDSubTLV().getBGPLS_ID() != null) {// alguna condicion? + localBgplsID = linkNLRI.getLocalNodeDescriptors().getBGPLSIDSubTLV().getBGPLS_ID().toString(); + } + if (linkNLRI.getRemoteNodeDescriptorsTLV().getBGPLSIDSubTLV().getBGPLS_ID() != null) {// alguna condicion? + remoteBgplsID = linkNLRI.getRemoteNodeDescriptorsTLV().getBGPLSIDSubTLV().getBGPLS_ID().toString(); + } + if (linkNLRI.getLocalNodeDescriptors().getIGPRouterID() != null) { + IGP_type = linkNLRI.getLocalNodeDescriptors().getIGPRouterID().getIGP_router_id_type(); + switch (IGP_type) { + case 1: + localIGPID = Integer.toString(linkNLRI.getLocalNodeDescriptors().getIGPRouterID().getISIS_ISO_NODE_ID()); + break; + case 2: + localIGPID = Integer.toString(linkNLRI.getLocalNodeDescriptors().getIGPRouterID().getISIS_ISO_NODE_ID()); + break; + case 3: + localIGPID = linkNLRI.getLocalNodeDescriptors().getIGPRouterID().getIpv4AddressOSPF().toString(); + + break; + default: + log.info("añadir este tipo de IGP Identifier por implementar "); + } + } + if (linkNLRI.getRemoteNodeDescriptorsTLV().getIGPRouterID() != null) { + IGP_type = linkNLRI.getRemoteNodeDescriptorsTLV().getIGPRouterID().getIGP_router_id_type(); + switch (IGP_type) { + case 1: + remoteBgplsID = Integer.toString(linkNLRI.getRemoteNodeDescriptorsTLV().getIGPRouterID().getISIS_ISO_NODE_ID()); + break; + case 2: + remoteBgplsID = Integer.toString(linkNLRI.getRemoteNodeDescriptorsTLV().getIGPRouterID().getISIS_ISO_NODE_ID()); + case 3: + remoteIGPID = linkNLRI.getRemoteNodeDescriptorsTLV().getIGPRouterID().getIpv4AddressOSPF().toString(); + break; + default: + log.info("añadir este tipo de IGP Identifier por implementar "); + } + } + + } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + localBgplsID.hashCode(); + result = 31 * result + iPv4RouterIDLocalNodeLATLV.hashCode(); + result = 31 * result + iPv4RouterIDNeighborNodeLATLV.hashCode(); + return result; + } + + @Override + public boolean equals(Object o) { + if (o == this) + return true; + if (!(o instanceof LinkNLRIMsg)) { + return false; + } + LinkNLRIMsg linkCk = (LinkNLRIMsg) o; + return linkCk.localBgplsID == localBgplsID && linkCk.iPv4RouterIDLocalNodeLATLV == iPv4RouterIDLocalNodeLATLV + && linkCk.localBgplsID == localBgplsID + && linkCk.iPv4RouterIDLocalNodeLATLV == iPv4RouterIDLocalNodeLATLV; + } + + public String toString() {// check type + String out = ""; + if (this.localBgplsID != null) + out = out + "ID: " + this.localBgplsID + " ";// esto es id router?? + if (this.iPv4RouterIDLocalNodeLATLV != null) + out = out + this.iPv4RouterIDLocalNodeLATLV.toString(); + if(this.localIGPID!=null) + out = out + " localIGPID: "+ this.localIGPID; + if (this.iPv4RouterIDNeighborNodeLATLV != null) + out = out + "---->" + this.iPv4RouterIDNeighborNodeLATLV.toString(); + if(this.remoteIGPID!=null) + out = out + " remoteIGPID: "+ this.remoteIGPID; + if (this.remoteBgplsID != null) + out = out + "ID: " + this.remoteBgplsID + " "; + if (this.localDomainID != null) + out = out + "\n AS_ID local: " + this.localDomainID.toString() + " "; + if (this.remoteDomainID != null) + out = out + "\n AS_ID remote: " + this.remoteDomainID.toString() + " "; + if (this.availableBw != 0) + out = out + "\n availableBW: " + this.availableBw + " "; + if (this.residualBw != 0) + out = out + "\n residualBw: " + this.residualBw + " "; + if (this.linkDelay != 0) + out = out + "\n linkDelay: " + this.linkDelay + " "; + return out; + + } + + public String getLearntFrom() { + return learntFrom; + } + + public void setLearntFrom(String learntFrom) { + this.learntFrom = learntFrom; + } + + public String getiPv4RouterIDLocalNodeLATLV() { + if (iPv4RouterIDLocalNodeLATLV != null) + return iPv4RouterIDLocalNodeLATLV.toString(); + else + return null;// NO DEBERIA SER NULL + } + + public void setiPv4RouterIDLocalNodeLATLV(Inet4Address iPv4RouterIDLocalNodeLATLV) { + this.iPv4RouterIDLocalNodeLATLV = iPv4RouterIDLocalNodeLATLV; + } + + public String getiPv4RouterIDNeighborNodeLATLV() { + if (iPv4RouterIDNeighborNodeLATLV != null) + return iPv4RouterIDNeighborNodeLATLV.toString(); + else + return null;// NO DEBERIA SER NULL + } + + public void setiPv4RouterIDNeighborNodeLATLV(Inet4Address iPv4RouterIDNeighborNodeLATLV) { + this.iPv4RouterIDNeighborNodeLATLV = iPv4RouterIDNeighborNodeLATLV; + } + + public Inet4Address getLocalDomainID() { + return localDomainID; + } + + public Inet4Address getRemoteDomainID() { + return remoteDomainID; + } + + public String getLocalBgplsID() { + return this.localBgplsID; + } + + public void setLocalBgplsID(String localBgplsID) { + this.localBgplsID = localBgplsID; + } + + public String getRemoteBgplsID() { + return this.remoteBgplsID; + } + + public void setRemoteBgplsID(String remoteBgplsID) { + this.remoteBgplsID = remoteBgplsID; + } + + public Inet4Address getLocalNodeIGPId() { + return LocalNodeIGPId; + } + + public Inet4Address getRemoteNodeIGPId() { + return RemoteNodeIGPId; + } + + public int getLinkDelay() { + return linkDelay; + } + + public int getLinkDelayVar() { + return linkDelayVar; + } + + public int getMinDelay() { + return minDelay; + } + + public int getMaxDelay() { + return maxDelay; + } + + public int getResidualBw() { + return residualBw; + } + + public int getAvailableBw() { + return availableBw; + } + + public int getUtilizedBw() { + return utilizedBw; + } + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/NodeNLRIMsg.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/NodeNLRIMsg.java new file mode 100644 index 000000000..958544f63 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/NodeNLRIMsg.java @@ -0,0 +1,197 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.models; + +import java.net.Inet4Address; +import java.net.InetAddress; +import java.util.ArrayList; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.net.InetAddresses; + +import es.tid.bgp.bgp4.update.fields.LinkNLRI; +import es.tid.bgp.bgp4.update.fields.NodeNLRI; +import es.tid.bgp.bgp4.update.tlv.node_link_prefix_descriptor_subTLVs.NodeDescriptorsSubTLV; + +public class NodeNLRIMsg { + + private ArrayList nodeDescriptorsSubTLV; + // Dominios + private Inet4Address localDomainID; + private Inet4Address remoteDomainID; + private Inet4Address areaID; + private Inet4Address bgplsID; + + private Inet4Address LocalNodeBGPId; + + private Inet4Address iPv4RouterIDLocalNodeLATLV; + private Inet4Address iPv4RouterIDNeighborNodeLATLV; + + private String localBgplsID; + private int remoteBgplsID; + + private Inet4Address as_number; + + private int IGP_type; + private Inet4Address IGPID = null; + private Logger log; + private String nodeName; + private String ISIS_ID_str; + private String router_id="-"; + + private String learntFrom; + + public NodeNLRIMsg(NodeNLRI nodeNLRI, String learntFrom, String nodeName) { + + log = LoggerFactory.getLogger("BGP4Server");// prueba logger + + this.learntFrom = learntFrom; + + if (nodeNLRI.getLocalNodeDescriptors().getAutonomousSystemSubTLV() != null) { + // inetAddr??? + as_number = nodeNLRI.getLocalNodeDescriptors().getAutonomousSystemSubTLV().getAS_ID(); + } + if (nodeNLRI.getLocalNodeDescriptors().getAreaID() != null) { + areaID = nodeNLRI.getLocalNodeDescriptors().getAreaID().getAREA_ID(); + } + if (nodeNLRI.getLocalNodeDescriptors().getBGPLSIDSubTLV() != null) { + localBgplsID=nodeNLRI.getLocalNodeDescriptors().getBGPLSIDSubTLV().getBGPLS_ID().toString(); + } + + if (nodeNLRI.getLocalNodeDescriptors().getIGPRouterID() != null) { + IGP_type = nodeNLRI.getLocalNodeDescriptors().getIGPRouterID().getIGP_router_id_type(); + switch (IGP_type) { + case 1: + ISIS_ID_str = Integer.toString(nodeNLRI.getLocalNodeDescriptors().getIGPRouterID().getISIS_ISO_NODE_ID()); + router_id=ISIS_ID_str; + case 2: + ISIS_ID_str = Integer.toString(nodeNLRI.getLocalNodeDescriptors().getIGPRouterID().getISIS_ISO_NODE_ID()); + router_id=ISIS_ID_str; + case 3: + IGPID = nodeNLRI.getLocalNodeDescriptors().getIGPRouterID().getIpv4AddressOSPF(); + if(IGPID!=null){ + router_id=IGPID.toString(); + }else{ + System.out.println("Null IGPID (type OSPF)"); + } + break; + default: + log.info("añadir este tipo de IGP Identifier por implementar "); + } + } + + if (nodeNLRI.getLocalNodeDescriptors().getBGPLSIDSubTLV() != null) { + if (nodeNLRI.getLocalNodeDescriptors().getBGPLSIDSubTLV().getBGPLS_ID() != null) { + LocalNodeBGPId = nodeNLRI.getLocalNodeDescriptors().getBGPLSIDSubTLV().getBGPLS_ID(); + } + } + + if (nodeName != null) { + this.nodeName = nodeName; + }else{ + this.nodeName= this.router_id; + } + log.info("End node processing"); + } + + public String toString() {// check type + // TODO: concatenate with stringBuffer + + String out = ""; + if (this.router_id != null) + out = out + "ID: " + this.router_id + " ";// esto es id router?? + if (this.iPv4RouterIDLocalNodeLATLV != null) + out = out + this.iPv4RouterIDLocalNodeLATLV.toString(); + if (this.iPv4RouterIDNeighborNodeLATLV != null) + out = out + "---->" + this.iPv4RouterIDNeighborNodeLATLV.toString(); + if(this.LocalNodeBGPId!=null) + out=out+"BGP_ID: "+this.LocalNodeBGPId+" "; + if(this.as_number!=null) + out=out+"AS_number: "+InetAddresses.coerceToInteger(this.as_number)+" "; + if (this.nodeName != null) + out = out + "Name node attribute: " + nodeName + " "; + if (this.ISIS_ID_str != null) + out = out + "ID node: " + this.ISIS_ID_str + " "; + if (this.as_number != null) + out = out + "AS number: " + this.as_number.toString() + " "; + return out; + + } + + public String getLearntFrom() { + return learntFrom; + } + + public void setLearntFrom(String learntFrom) { + this.learntFrom = learntFrom; + } + + public String getLocalBgplsID() { + return this.localBgplsID; + } + + public void setLocalBgplsID(String localBgplsID) { + this.localBgplsID = localBgplsID; + } + + public String getNodeName() { + return nodeName; + } + + public Inet4Address getIGPID() { + return IGPID; + } + + public Inet4Address getBgplsID() { + return bgplsID; + } + + public String getRouterID(){ + return router_id; + } + + public void setBgplsID(Inet4Address bgplsID) { + this.bgplsID = bgplsID; + } + + public Inet4Address getAs_number() { + return as_number; + } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + localBgplsID.hashCode(); + result = 31 * result + iPv4RouterIDLocalNodeLATLV.hashCode(); + result = 31 * result + iPv4RouterIDNeighborNodeLATLV.hashCode(); + return result; + } + + @Override + public boolean equals(Object o) { + if (o == this) + return true; + if (!(o instanceof NodeNLRIMsg)) { + return false; + } + NodeNLRIMsg nodeCk = (NodeNLRIMsg) o; + return nodeCk.localBgplsID == localBgplsID && nodeCk.iPv4RouterIDLocalNodeLATLV == iPv4RouterIDLocalNodeLATLV + && nodeCk.localBgplsID == localBgplsID + && nodeCk.iPv4RouterIDLocalNodeLATLV == iPv4RouterIDLocalNodeLATLV; + } + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/PathAttributeMsg.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/PathAttributeMsg.java new file mode 100644 index 000000000..11bf355d0 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/PathAttributeMsg.java @@ -0,0 +1,89 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.models; + +import java.net.Inet4Address; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; + +import es.tid.bgp.bgp4.update.fields.pathAttributes.LinkStateAttribute; +import es.tid.bgp.bgp4.update.tlv.BGP4TLVFormat; +import es.tid.bgp.bgp4.update.tlv.linkstate_attribute_tlvs.IPv4RouterIDLocalNodeLinkAttribTLV; +import es.tid.bgp.bgp4.update.tlv.linkstate_attribute_tlvs.NodeNameNodeAttribTLV; + +public class PathAttributeMsg { + + + private NodeNameNodeAttribTLV nodeNameTLV; + private byte[] data; + private String nodeName; + private Inet4Address addrLocal; + + + public PathAttributeMsg(LinkStateAttribute att) { + + + if(att.getNodeNameTLV()!=null) { + + nodeNameTLV=att.getNodeNameTLV(); + data=nodeNameTLV.getTlv_bytes(); + int b = nodeNameTLV.getTotalTLVLength(); + int c = nodeNameTLV.getTLVValueLength(); + byte [] fin= Arrays.copyOfRange(data, b - c, b); + nodeName = new String(fin , StandardCharsets.UTF_8); + } + if(att.getIPv4RouterIDLocalNodeLATLV()!=null) { + addrLocal=att.getIPv4RouterIDLocalNodeLATLV().getIpv4Address(); + } + + } + public String toString() { + String out=""; + if(this.nodeName!=null) + out=out+"NODE name "+nodeName; + if(this.addrLocal!=null) + out=out+"NODE IP "+addrLocal.toString(); + + return out; + } + + public String getNodeName() { + return nodeName; + } + public void setNodeName(String nodeName) { + this.nodeName = nodeName; + } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + nodeName.hashCode(); + return result; + } + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (!(o instanceof PathAttributeMsg)) { + return false; + } + PathAttributeMsg pathCk = (PathAttributeMsg) o; + return pathCk.nodeName == nodeName; + } + public Inet4Address getAddrLocal() { + return addrLocal; + } + + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/UpdateMsg.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/UpdateMsg.java new file mode 100644 index 000000000..37d87e683 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/UpdateMsg.java @@ -0,0 +1,99 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.models; + +import java.net.InetAddress; +import java.util.ArrayList; +import java.util.List; + +public class UpdateMsg { + + private int AFI; + private int asPathSegment; + private InetAddress nextHop; + private String learntFrom; + + private NodeNLRIMsg node; + private LinkNLRIMsg link; + private PathAttributeMsg path; + private List linkList = new ArrayList<>(); + private List nodeList = new ArrayList<>(); + + public List getLinkList(){ + return this.linkList; + } + public List getNodeList(){ + return this.nodeList; + } + public void addNode(NodeNLRIMsg node) { + this.nodeList.add(node); + } + public int getAFI() { + return AFI; + } + public String getLearntFrom() { + return learntFrom; + } + public void setLearntFrom(String learntFrom) { + this.learntFrom = learntFrom; + } + public void setAFI(int aFI) { + AFI = aFI; + } + public int getAsPathSegment() { + return asPathSegment; + } + public void setAsPathSegment(int asPathSegment) { + this.asPathSegment = asPathSegment; + } + public InetAddress getNextHop() { + return nextHop; + } + public void setNextHop(InetAddress nextHop) { + this.nextHop = nextHop; + } + public NodeNLRIMsg getNode() { + return node; + } + public void setNode(NodeNLRIMsg node) { + this.node = node; + } + // public LinkNLRIMsg getLink() { + // return link; + // } + public boolean linkCheck(){ + return linkList.size()>0; + } + public boolean nodeCheck(){ + return nodeList.size()>0; + } + public void setLink(LinkNLRIMsg link) { + this.link = link; + } + public void addLink(LinkNLRIMsg link) { + this.linkList.add(link); + } + public PathAttributeMsg getPath() { + return path; + } + public void setPath(PathAttributeMsg path) { + this.path = path; + } + + + + + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/UpdateMsgList.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/UpdateMsgList.java new file mode 100644 index 000000000..6fd30c6cb --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/models/UpdateMsgList.java @@ -0,0 +1,151 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.models; + +import java.net.InetAddress; +import java.util.LinkedList; +import java.util.List; + +public class UpdateMsgList { + + + /* Print purposes and debug*/ + List nodeList = new LinkedList<>(); + List linkList = new LinkedList<>(); + List pathList = new LinkedList<>(); + /**/ + public UpdateMsgList() { + } + + + public String toString() { + + String out ="Update Message: "; + if(nodeList!=null) { + out=out+nodeList.toString()+"\n"; + } + if(linkList!=null) { + out=out+linkList.toString()+"\n"; + } + if(pathList!=null) { + out=out+pathList.toString()+"\n"; + } + + return out; + + } + public void addLinkToJson(LinkNLRIMsg link) { + + if(link==null) + return; + boolean exists = false; + for (LinkNLRIMsg linkInList : linkList) { // list being the LinkedList + if (link.equals(linkInList)) { + exists = true; + break; + } + } + if (!exists) { + linkList.add(link); + } + } + public void addNodeToJson(NodeNLRIMsg node, String currentName) {//comprobar que existe? + + if(node==null) + return; + boolean exists = false; + for (NodeNLRIMsg nodeInList : nodeList) { // list being the LinkedList + if (node.equals(nodeInList)) { + exists = true; + break; + } + } + if (!exists) { + nodeList.add(node); + } + + } + public void addpathToJson(PathAttributeMsg path) { + + boolean exists = false; + if(path.getNodeName()==null) { + return; + } + for (PathAttributeMsg pathInList : pathList) { // list being the LinkedList + if (path.equals(pathInList) ) { + exists = true; + break; + } + } + if (!exists) { + pathList.add(path); + } + + } + + public List getNodeList() { + return nodeList; + } + + public List getLinkList() { + return linkList; + } + + public List getPathList() { + return pathList; + } + + public void addNodeToList(NodeNLRIMsg node) { + nodeList.add(node); + } + public void addLinkToList(LinkNLRIMsg link) { + linkList.add(link); + } + public void addPathToList(PathAttributeMsg path) { + pathList.add(path); + } + + public UpdateMsgList id2Name() { + + UpdateMsgList update=new UpdateMsgList(); + update.nodeList=this.nodeList; + update.pathList=this.pathList; + List newLinkList = new LinkedList<>(); + + for (LinkNLRIMsg linkInList : linkList) { + LinkNLRIMsg link=linkInList; + + for(NodeNLRIMsg nodeInList: update.nodeList) { + if((linkInList.getLocalBgplsID().equals(nodeInList.getLocalBgplsID()))) { + link.setLocalBgplsID(nodeInList.getNodeName()); + } + } + + for(NodeNLRIMsg nodeInList: update.nodeList) { + if((linkInList.getRemoteBgplsID().equals(nodeInList.getLocalBgplsID()))) { + link.setRemoteBgplsID(nodeInList.getNodeName()); + } + } + + + newLinkList.add(link); + } + update.linkList=newLinkList; + + return update; + + } + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4Exception.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4Exception.java new file mode 100644 index 000000000..736f6cd3e --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4Exception.java @@ -0,0 +1,20 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.peer; + +public class BGP4Exception extends Exception { + + private static final long serialVersionUID = 1L; +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4LSPeerInfo.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4LSPeerInfo.java new file mode 100644 index 000000000..768e4a87b --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4LSPeerInfo.java @@ -0,0 +1,85 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.peer; + +import java.net.Inet4Address; + +public class BGP4LSPeerInfo { + /** + * IP Address of the remote Peer + */ + private Inet4Address peerIP; + + /** + * Experimental USE Only + * Default port is 179 + * For testing and development, alternative ports are allowed. + */ + private int peerPort; + + /** + * If the remote peer is a consumer and we need to send the topology + */ + private boolean sendToPeer; + + /** + * If the remote peer is a generator of topology and we are consumers + */ + private boolean updateFromPeer; + + + + public BGP4LSPeerInfo() { + this.peerPort=179; + } + + public Inet4Address getPeerIP() { + return peerIP; + } + + public void setPeerIP(Inet4Address peerIP) { + this.peerIP = peerIP; + } + + public int getPeerPort() { + return peerPort; + } + + public void setPeerPort(int peerPort) { + this.peerPort = peerPort; + } + + public boolean isSendToPeer() { + return sendToPeer; + } + + public void setSendToPeer(boolean sendToPeer) { + this.sendToPeer = sendToPeer; + } + + public boolean isUpdateFromPeer() { + return updateFromPeer; + } + + public void setUpdateFromPeer(boolean updateFromPeer) { + this.updateFromPeer = updateFromPeer; + } + + + + + + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4Parameters.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4Parameters.java new file mode 100644 index 000000000..e8958d306 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4Parameters.java @@ -0,0 +1,540 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.peer; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import java.net.Inet4Address; +import java.net.UnknownHostException; +import java.util.LinkedList; + +/** + * Parameters to configure the BGP4 session + * @author mcs + * + */ +public class BGP4Parameters { + + private Logger log = LoggerFactory.getLogger("BGP4Peer"); + /** + * TCP port where the BGP is listening for incoming bgp4 connections + * Experimental use only. Default and standard is 179 + */ + private int BGP4Port = 179; + + /** + * TCP port to connect to manage the BGP connection + */ + private int BGP4ManagementPort = 1112; + /** + * Local BGP4 address of this peer + */ + private String localBGPAddress = "127.0.0.1"; + /** + * Local port to connect with BGP Peer. + */ + private int localBGPPort = 0; + /** + * Log file + */ + private String BGP4LogFile="BGP4Parser.log"; + /** + * Log file Client + */ + private String BGP4LogFileClient="BGP4Client.log"; + + + /** + * Log file Client + */ + private String BGP4LogFileServer="BGP4Server.log"; + + + /** + * Name of the configuration file + */ + private String confFile; + + /** + * If the tcp no delay option is used or not. + */ + private boolean nodelay=false; + /** + * Waiting Time to connect to clients + */ + long delay = 6000; + /** + * List of peers to establish connection. + */ + private LinkedList peersToConnect; + + /** + * Parameter used to set traces meanwhile the execution. + */ + private boolean setTraces=true; + /** + * OPEN PARAMENTERS + */ + int holdTime=90; + /** + * OPEN PARAMENTERS + */ + + private boolean isTest=false; + + /** + * Time between sending keepalives + */ + int keepAliveTimer=30; + + /** + * Time between topology updates + */ + long sendTopoDelay=30000; + + private boolean saveTopologyDB=false; + + private Inet4Address topologyDBIP; + + private int topologyDBport; + + public int getKeepAliveTimer() { + return keepAliveTimer; + } + public void setKeepAliveTimer(int keepAliveTimer) { + this.keepAliveTimer = keepAliveTimer; + } + String BGPIdentifier = null; + int myAutonomousSystem=1; + int version=0x04; + + /** + * This parameter can have three options: fromXML, fromOSPF, fromBGP + * Explain the way the topology module learns the topology + */ + private String learnTopology="fromBGP"; + /** + * XML File to read and generate the topology + */ + private String topologyFile; + + + private int numberTriesToConnect=3; + /** + * True: This peer sends the interdomain links of the topology to other peers + * False: This peer does NOT send the topology to other peers + */ + private boolean sendTopology=false; + /** + * True: This peer sends the whole topology to other peers + * False: This peer does NOT send the intradomain linksto other peers + */ + private boolean sendIntradomainLinks=false; + + + + /** + * Instance identifier for NodeNLRI (Types defined in class InstanceIDTypes) + */ + private int instanceID=0; + /** + * Constructor + */ + BGP4Parameters(){ + confFile="BGP4Parameters.xml"; + peersToConnect =new LinkedList(); + } + /** + * Constructor + */ + BGP4Parameters(String confFile){ + peersToConnect =new LinkedList(); + + if (confFile!=null){ + this.confFile=confFile; + }else { + confFile="BGP4Parameters.xml"; + } + + } + + + + public void initialize(){ + + try { + + System.out.println("Parsing Config File::"+confFile); + + SAXParserFactory factory = SAXParserFactory.newInstance(); + SAXParser saxParser = factory.newSAXParser(); + + + DefaultHandler handler = new DefaultHandler() { + boolean peer = false; + boolean send = false; + boolean receive = false; + boolean peerPort = false; + BGP4LSPeerInfo peerInfo=null; + + String tempVal; + + public void startElement(String uri, String localName, + String qName, Attributes attributes) + throws SAXException { + + if (qName.equalsIgnoreCase("configPeer")){ + log.debug("Found peer configuration"); + } + else if (qName.equalsIgnoreCase("peer")){ + peer = true; + } + else if (qName.equalsIgnoreCase("export")){ + send = true; + } + else if (qName.equalsIgnoreCase("import")){ + receive = true; + }else if (qName.equalsIgnoreCase("peerPort")){ + peerPort = true; + } + + } + + public void endElement(String uri, String localName, + String qName) + throws SAXException { + if(qName.equalsIgnoreCase("BGP4Port")) { + BGP4Port=Integer.parseInt(tempVal.trim()); + + } + else if (qName.equalsIgnoreCase("BGP4ManagementPort")){ + BGP4ManagementPort = Integer.parseInt(tempVal.trim()); + } + + else if (qName.equalsIgnoreCase("BGP4LogFile")) { + BGP4LogFile=tempVal.trim(); + } + else if (qName.equalsIgnoreCase("BGP4LogFileClient")) { + BGP4LogFileClient=tempVal.trim(); + } + else if (qName.equalsIgnoreCase("BGP4LogFileServer")) { + BGP4LogFileServer=tempVal.trim(); + } + else if (qName.equalsIgnoreCase("nodelay")) { + nodelay=Boolean.parseBoolean(tempVal.trim()); + } + else if (qName.equalsIgnoreCase("isTest")) { + isTest=Boolean.parseBoolean(tempVal.trim()); + } + + else if (qName.equalsIgnoreCase("setTraces")) { + setTraces=Boolean.parseBoolean(tempVal.trim()); + } + else if (qName.equalsIgnoreCase("saveTopologyDB")) { + saveTopologyDB=Boolean.parseBoolean(tempVal.trim()); + } + else if (qName.equalsIgnoreCase("topologyDBIP")) { + try { + topologyDBIP =(Inet4Address)Inet4Address.getByName(tempVal.trim()); + } catch (UnknownHostException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + else if (qName.equalsIgnoreCase("topologyDBport")) { + topologyDBport=Integer.parseInt(tempVal.trim()); + } + else if (qName.equalsIgnoreCase("sendTopology")) { + sendTopology=Boolean.parseBoolean(tempVal.trim()); + } + else if (qName.equalsIgnoreCase("sendIntradomainLinks")) { + sendIntradomainLinks=Boolean.parseBoolean(tempVal.trim()); + sendTopology = true;//si se envian los intradomain entonces se enviara la topologia entera + } + + + else if(qName.equalsIgnoreCase("holdTime")) { + holdTime=Integer.parseInt(tempVal.trim()); + } + else if(qName.equalsIgnoreCase("keepAliveTimer")) { + keepAliveTimer=Integer.parseInt(tempVal.trim()); + } + else if (qName.equalsIgnoreCase("version")){ + version = Integer.parseInt(tempVal.trim()); + } + else if (qName.equalsIgnoreCase("myAutonomousSystem")){ + myAutonomousSystem = Integer.parseInt(tempVal.trim()); + } + else if (qName.equalsIgnoreCase("localBGPAddress")){//El BGP Identifier es la local BGP Address. + //BGPIdentifier = tempVal.trim(); + localBGPAddress=tempVal.trim(); + } + else if (qName.equalsIgnoreCase("BGPIdentifier")){//El BGP Identifier es la local BGP Address. + BGPIdentifier = tempVal.trim(); + } + else if (qName.equalsIgnoreCase("delay")){ + delay = Long.parseLong(tempVal.trim()); + } + else if (qName.equalsIgnoreCase("sendTopoDelay")){ + sendTopoDelay = Long.parseLong(tempVal.trim()); + } + /* + else if (qName.equalsIgnoreCase("peer")){ + String peerBGP_IPaddress = tempVal.trim(); + peersToConnect.add(peerBGP_IPaddress); + }*/ + else if (qName.equalsIgnoreCase("TopologyFile")) { + topologyFile=tempVal.trim(); + } + else if (qName.equalsIgnoreCase("learnTopology")) { + learnTopology=tempVal.trim(); + } + else if (qName.equalsIgnoreCase("numberTriesToConnect")){ + numberTriesToConnect = Integer.parseInt(tempVal.trim()); + } + else if (qName.equalsIgnoreCase("instanceID")){ + instanceID = Integer.parseInt(tempVal.trim()); + } + else if (qName.equalsIgnoreCase("localBGPPort")){ + localBGPPort = Integer.parseInt(tempVal.trim()); + } +// else if (qName.equalsIgnoreCase("configPeer")){ +// log.info("peers....." + peersToConnect.toString()); +// } + } + + + public void characters(char[] ch, int start, int length) throws SAXException { + tempVal = new String(ch,start,length); + + if(peer){ + peerInfo= new BGP4LSPeerInfo(); + + String peerBGP_IPaddress = new String(ch, start, length); + Inet4Address peerBGPIP; + try { + peerBGPIP=(Inet4Address)Inet4Address.getByName(peerBGP_IPaddress.trim()); + peerInfo.setPeerIP(peerBGPIP); + } catch (UnknownHostException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + peersToConnect.add(peerInfo); + peer = false; + } + else if(send){ + String sendInfo = new String(ch, start, length); + peerInfo.setSendToPeer(Boolean.parseBoolean(sendInfo.trim())); + send = false; + } + else if(receive){ + String update_from = new String(ch, start, length); + peerInfo.setUpdateFromPeer(Boolean.parseBoolean(update_from.trim())); + receive = false; + }else if (peerPort){ + String peer_port = new String(ch, start, length); + peerInfo.setPeerPort(Integer.parseInt(peer_port.trim())); + peerPort = false; + } + } + }; + saxParser.parse(confFile, handler); + + }catch (Exception e) { + log.error("Problems reading config"); + e.printStackTrace(); + System.exit(1); + } + + } + public int getBGP4Port() { + return BGP4Port; + } + public void setBGP4Port(int bGP4Port) { + BGP4Port = bGP4Port; + } + public int getBGP4ManagementPort() { + return BGP4ManagementPort; + } + public void setBGP4ManagementPort(int bGP4ManagementPort) { + BGP4ManagementPort = bGP4ManagementPort; + } + public String getBGP4LogFile() { + return BGP4LogFile; + } + public void setBGP4LogFile(String bGP4LogFile) { + BGP4LogFile = bGP4LogFile; + } + public boolean isSetTraces() { + return setTraces; + } + public void setSetTraces(boolean setTraces) { + this.setTraces = setTraces; + } + public boolean isTest() { + return isTest; + } + public void setisTest(boolean test) { + this.isTest = test; + } + + public String getConfFile() { + return confFile; + } + public void setConfFile(String confFile) { + this.confFile = confFile; + } + public boolean isNodelay() { + return nodelay; + } + public void setNodelay(boolean nodelay) { + this.nodelay = nodelay; + } + public int getHoldTime() { + return holdTime; + } + public void setHoldTime(int holdTime) { + this.holdTime = holdTime; + } + public String getBGPIdentifier() { + return BGPIdentifier; + } + public void setBGPIdentifier(String bGPIdentifier) { + BGPIdentifier = bGPIdentifier; + } + public int getMyAutonomousSystem() { + return myAutonomousSystem; + } + public void setMyAutonomousSystem(int myAutonomousSystem) { + this.myAutonomousSystem = myAutonomousSystem; + } + public int getVersion() { + return version; + } + public void setVersion(int version) { + this.version = version; + } + + public LinkedList getPeersToConnect() { + return peersToConnect; + } + public void setPeersToConnect(LinkedList peersToConnect) { + this.peersToConnect = peersToConnect; + } + + public String getLearnTopology() { + return learnTopology; + } + public void setLearnTopology(String learnTopology) { + this.learnTopology = learnTopology; + } + public String getTopologyFile() { + return topologyFile; + } + public void setTopologyFile(String topologyFile) { + this.topologyFile = topologyFile; + } + + public int getNumberTriesToConnect() { + return numberTriesToConnect; + } + public void setNumberTriesToConnect(int numberTriesToConnect) { + this.numberTriesToConnect = numberTriesToConnect; + } + public long getDelay() { + return delay; + } + public void setDelay(long delay) { + this.delay = delay; + } + public boolean isSendTopology() { + return sendTopology; + } + public void setSendTopology(boolean sendTopology) { + this.sendTopology = sendTopology; + } + public String getBGP4LogFileClient() { + return BGP4LogFileClient; + } + public void setBGP4LogFileClient(String bGP4LogFileClient) { + BGP4LogFileClient = bGP4LogFileClient; + } + public String getBGP4LogFileServer() { + return BGP4LogFileServer; + } + public void setBGP4LogFileServer(String bGP4LogFileServer) { + BGP4LogFileServer = bGP4LogFileServer; + } + public int getInstanceID() { + return instanceID; + } + public void setInstanceID(int instanceID) { + this.instanceID = instanceID; + } + public boolean isSendIntradomainLinks() { + return sendIntradomainLinks; + } + + public void setSendIntradomainLinks(boolean sendIntradomainLinks) { + this.sendIntradomainLinks = sendIntradomainLinks; + } + + + public String getLocalBGPAddress() { + return localBGPAddress; + } + public void setLocalBGPAddress(String localBGPAddress) { + this.localBGPAddress = localBGPAddress; + } + public int getLocalBGPPort() { + return localBGPPort; + } + + public long getSendTopoDelay() { + return sendTopoDelay; + } + public void setSendTopoDelay(long sendTopoDelay) { + this.sendTopoDelay = sendTopoDelay; + } + public boolean isSaveTopologyDB() { + return saveTopologyDB; + } + public void setSaveTopologyDB(boolean saveTopologyDB) { + this.saveTopologyDB = saveTopologyDB; + } + public Inet4Address getTopologyDBIP() { + return topologyDBIP; + } + public void setTopologyDBIP(Inet4Address topologyDBIP) { + this.topologyDBIP = topologyDBIP; + } + public int getTopologyDBport() { + return topologyDBport; + } + public void setTopologyDBport(int topologyDBport) { + this.topologyDBport = topologyDBport; + } + + + + + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4SessionClientManager.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4SessionClientManager.java new file mode 100644 index 000000000..75694e90c --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4SessionClientManager.java @@ -0,0 +1,160 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.peer; + +import eu.teraflow.tid.bgp4Peer.bgp4session.BGP4SessionClient; +import eu.teraflow.tid.bgp4Peer.bgp4session.BGP4SessionExistsException; +import eu.teraflow.tid.bgp4Peer.bgp4session.BGP4SessionsInformation; +import eu.teraflow.tid.bgp4Peer.updateTEDB.UpdateDispatcher; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.Inet4Address; + +/** + * Client session manager + * @author mcs + * + */ +public class BGP4SessionClientManager implements Runnable{ + + + + private BGP4SessionClient bgp4SessionClient; + private Logger log; + + BGP4SessionsInformation bgp4SessionInformation; + /** + * peer contains the IP address and port where the peer listens. + */ + private BGP4LSPeerInfo peer; + private Inet4Address peerIP; + private String localBGP4Address; + private int localBGP4Port; + private int holdTime; + private int keepAliveTimer; + private Inet4Address BGPIdentifier; + private int version = 4; + private int myAutonomousSystem; + private UpdateDispatcher ud; + private Boolean updateFrom; + private Boolean sendTo; + + public BGP4SessionClientManager(BGP4SessionsInformation bgp4SessionInformation,UpdateDispatcher ud, BGP4LSPeerInfo peer,int bgp4Port,String my_IPAddress,int my_bgp4Port , int holdTime,Inet4Address BGPIdentifier,int version,int myAutonomousSystem, int my_keepAliveTimer){ + log=LoggerFactory.getLogger("BGP4Peer"); + this.bgp4SessionInformation=bgp4SessionInformation; + this.holdTime=holdTime; + this.BGPIdentifier=BGPIdentifier; + this.version = version; + this.myAutonomousSystem=myAutonomousSystem; + this.peer = peer; + this.ud=ud; + this.localBGP4Address=my_IPAddress; + this.localBGP4Port=my_bgp4Port; + this.keepAliveTimer = my_keepAliveTimer; + this.peerIP=peer.getPeerIP(); + this.setSendTo(peer.isSendToPeer()); + this.setUpdateFrom(peer.isUpdateFromPeer()); + + } + + /** + * + * + * + */ + public void run(){ + if(bgp4SessionClient != null){ + if (bgp4SessionClient.isAlive()){ + if (bgp4SessionClient.isInterrupted()){ + log.debug("Thread alive... backup session dead"); + + } + log.debug("Session alive and not interrupted"); + return; + } + else{ + try{ + bgp4SessionInformation.notifySessionStart(peerIP); + log.debug("Session with BGP-LS peer"+peer +" dead, trying to establish new session"); + bgp4SessionClient= new BGP4SessionClient(bgp4SessionInformation,ud,peer.getPeerIP(),peer.getPeerPort(),holdTime,BGPIdentifier,version,myAutonomousSystem,localBGP4Address, localBGP4Port,keepAliveTimer); + bgp4SessionClient.setSendTo(sendTo); + bgp4SessionClient.setUpdateFrom(updateFrom); + bgp4SessionClient.start(); + } catch(BGP4SessionExistsException e){ + log.debug("Checked that there is already a peer initiated session with "+this.peerIP); + } + + return; + } + } else { + try{ + bgp4SessionInformation.notifySessionStart(peerIP); + log.info("Trying to establish new session with peer "+ peer.getPeerIP()+" on port "+peer.getPeerPort()); + bgp4SessionClient = new BGP4SessionClient(bgp4SessionInformation,ud, peer.getPeerIP(), peer.getPeerPort(), holdTime, BGPIdentifier, + version,myAutonomousSystem,localBGP4Address, localBGP4Port ,keepAliveTimer); + bgp4SessionClient.setSendTo(sendTo); + bgp4SessionClient.setUpdateFrom(updateFrom); + bgp4SessionClient.start(); + + } catch(BGP4SessionExistsException e){ + log.debug("No need to start new connection with "+this.peerIP); + } + + + return; + + } + + } + public BGP4SessionClient getBgp4SessionClient() { + return bgp4SessionClient; + } + + public void setBgp4SessionClient(BGP4SessionClient bgp4SessionClient) { + this.bgp4SessionClient = bgp4SessionClient; + } + + public void killBGP4Session(){ + bgp4SessionClient.killSession(); + } + + public void closeBGP4Session(){ + log.info("Closing BGP4Session"); + if (bgp4SessionClient.isAlive()){ + //FIXME reason for close???? + bgp4SessionClient.close(); + } + + } + + public Boolean getUpdateFrom() { + return updateFrom; + } + + public void setUpdateFrom(Boolean updateFrom) { + this.updateFrom = updateFrom; + } + + public Boolean getSendTo() { + return sendTo; + } + + public void setSendTo(Boolean sendTo) { + this.sendTo = sendTo; + } + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4SessionServerManager.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4SessionServerManager.java new file mode 100644 index 000000000..ccb59fa2e --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGP4SessionServerManager.java @@ -0,0 +1,160 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.peer; + +import eu.teraflow.tid.bgp4Peer.bgp4session.BGP4PeerInitiatedSession; +import eu.teraflow.tid.bgp4Peer.bgp4session.BGP4SessionsInformation; +import eu.teraflow.tid.bgp4Peer.updateTEDB.UpdateDispatcher; +import eu.teraflow.tid.tedb.TEDB; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.Inet4Address; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.LinkedList; + +public class BGP4SessionServerManager implements Runnable { + private BGP4PeerInitiatedSession bgp4SessionServer; + private Logger log; + BGP4SessionsInformation bgp4SessionsInformation; + int bgp4Port; + private int holdTime; + private int keepAliveTimer; + private Inet4Address BGPIdentifier; + private int version = 4; + private int myAutonomousSystem; + private boolean noDelay; + private boolean isTest=false; + private TEDB tedb; + private UpdateDispatcher ud; + Inet4Address localBGP4Address; + private Boolean updateFrom; + private Boolean sendTo; + + private LinkedList peersToConnect; + + public BGP4SessionServerManager(BGP4SessionsInformation bgp4SessionInformation, TEDB tedb,UpdateDispatcher ud, int bgp4Port,int holdTime,Inet4Address BGPIdentifier,int version,int myAutonomousSystem,boolean noDelay,Inet4Address localAddress ,int mykeepAliveTimer, LinkedList peersToConnect ){ + log = LoggerFactory.getLogger("BGP4Peer"); + this.holdTime=holdTime; + this.BGPIdentifier=BGPIdentifier; + this.version = version; + this.myAutonomousSystem=myAutonomousSystem; + this.bgp4SessionsInformation=bgp4SessionInformation; + this.bgp4Port=bgp4Port; + this.noDelay=noDelay; + this.tedb=tedb; + this.ud=ud; + this.localBGP4Address=localAddress; + this.keepAliveTimer = mykeepAliveTimer; + this.peersToConnect=peersToConnect; + } + + public BGP4SessionServerManager(BGP4SessionsInformation bgp4SessionInformation, TEDB tedb,UpdateDispatcher ud, int bgp4Port,int holdTime,Inet4Address BGPIdentifier,int version,int myAutonomousSystem,boolean noDelay,Inet4Address localAddress ,int mykeepAliveTimer, LinkedList peersToConnect, boolean test){ + log = LoggerFactory.getLogger("BGP4Peer"); + this.holdTime=holdTime; + this.BGPIdentifier=BGPIdentifier; + this.version = version; + this.myAutonomousSystem=myAutonomousSystem; + this.bgp4SessionsInformation=bgp4SessionInformation; + this.bgp4Port=bgp4Port; + this.noDelay=noDelay; + this.tedb=tedb; + this.ud=ud; + this.localBGP4Address=localAddress; + this.keepAliveTimer = mykeepAliveTimer; + this.peersToConnect=peersToConnect; + this.isTest=test; + } + + + public Boolean getSendTo() { + return sendTo; + } + + public void setSendTo(Boolean sendTo) { + this.sendTo = sendTo; + } + + public Boolean getUpdateFrom() { + return updateFrom; + } + + public void setUpdateFrom(Boolean updateFrom) { + this.updateFrom = updateFrom; + } + + @Override + public void run() { + + + + ServerSocket serverSocket = null; + boolean listening = true; + try { + log.debug("SERVER Listening on port: "+ bgp4Port); + log.debug("SERVER Listening on address: "+ localBGP4Address); + serverSocket = new ServerSocket( bgp4Port,0,localBGP4Address); + } catch (IOException e) { + log.error("Could not listen on port: "+ bgp4Port); + System.exit(-1); + } + while (listening) { + try { + Socket sock=serverSocket.accept(); + bgp4SessionServer = new BGP4PeerInitiatedSession(sock,bgp4SessionsInformation,ud,holdTime,BGPIdentifier,version,myAutonomousSystem,noDelay,keepAliveTimer); + if (isTest){ + log.info("isTest"); + bgp4SessionServer.setSendTo(true); + bgp4SessionServer.start(); + } + else { + log.info("Not Test"); + for (int i = 0; i < this.peersToConnect.size(); i++) { + try { + Inet4Address add = peersToConnect.get(i).getPeerIP(); + if (add == null) { + log.warn("peer IP address shouldn't be null"); + } else { + if (add.equals(sock.getInetAddress())) { + log.debug("FOUND " + add); + bgp4SessionServer.setSendTo(this.peersToConnect.get(i).isSendToPeer()); + } + } + + } catch (Exception e) { + e.printStackTrace(); + } + + } + bgp4SessionServer.start(); + } + }catch (Exception e) { + e.printStackTrace(); + } + } + try { + log.info("Closing the socket"); + serverSocket.close(); + + }catch (Exception e) { + e.printStackTrace(); + } + + } + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGPPeer.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGPPeer.java new file mode 100644 index 000000000..bdddd4379 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGPPeer.java @@ -0,0 +1,407 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.peer; + +import eu.teraflow.tid.bgp4Peer.bgp4session.BGP4SessionsInformation; +import eu.teraflow.tid.bgp4Peer.management.BGP4ManagementServer; +import eu.teraflow.tid.bgp4Peer.updateTEDB.UpdateDispatcher; +import eu.teraflow.tid.tedb.*; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Hashtable; +import java.util.LinkedList; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + + +/** + * BGP-LS Speaker. + * This class is a BGP-LS peer which has two modes: + * - Listens to incoming connections + * - Launches new BGP session with a list of peers. + * It can send periodically its learnt topology to other peers. + * TEDB can be initialized from: + * - XML file with the topolgoy + * - Other BGP-LS Sessions + * + * @author pac ogondio + * + */ +public class BGPPeer { + /** + * Session server. It opens a socket to listen to new connections. + */ + private BGP4SessionServerManager bgp4SessionServer; + /** + * Session client. It connects to peers. + */ + private BGP4SessionClientManager bgp4SessionClientManager; + /** + * BGP4 parameters. Needed to configure the connections. + */ + private BGP4Parameters params; + + /** + * List of opened BGP4 sessions. + */ + private BGP4SessionsInformation bgp4SessionsInformation; + + /** + * Topology database only for interDomain Links. + */ + private MultiDomainTEDB multiDomainTEDB; + + /** + * Table with domainID - TEDB. + * The BGP-LS Peer can have several domains + */ + private Hashtable intraTEDBs; + + /** + * Full TEDB with all Links + */ + + private SimpleTEDB fullTEDB; + + + /** + * Class to send periodically the topology + */ + //private DomainTEDB readDomainTEDB; + + /** + * True: This peer sends the topology to other peers + * False: This peer does NOT send the topology to other peers + */ + private boolean sendTopology; + /** + * + */ + private SendTopology sendTopologyTask; + /** + * + */ + private boolean saveTopology; + + private SaveTopologyinDB saveTopologyDB; + + /** + * + */ + /** + * List of peers to establish connections. + */ + private LinkedList peersToConnect; + + //Whitelist and blacklist not yet implemented + + /** + * Loggers + */ + private Logger logParser; + private Logger logClient; + private Logger logServer; + /** + * Class to read and process the BGP4 update messages + */ + private UpdateDispatcher ud; + /** + * Executor. To execute the session server, to execute periodically the session client. + */ + private ScheduledThreadPoolExecutor executor; + + /** + * Function to configure the BGP4 Peer without specifying the file. It will read a file with name: BGP4Parameters.xml + */ + public void configure (){ + this.configure (null); + } + + /** + * Function to configure the BGP4 peer. + * It created the loggers, the executor, + * @param nameParametersFile Name of the Parameters File + */ + public void configure(String nameParametersFile){ + configure(nameParametersFile, null, null); + } + + /** + * Function to configure the BGP4 peer. + * It created the loggers, the executor, + * @param nameParametersFile Name of the Parameters File + * @param multiTEDB multidomain database + * @param iTEDBs internal domains database + */ + public void configure(String nameParametersFile, MultiDomainTEDB multiTEDB, Hashtable iTEDBs){ + //First of all, read the parameters + if (nameParametersFile != null){ + params=new BGP4Parameters(nameParametersFile); + }else{ + params=new BGP4Parameters(); + } + params.initialize(); + peersToConnect = params.getPeersToConnect(); + sendTopology = params.isSendTopology(); + saveTopology = params.isSaveTopologyDB(); + + //Initialize loggers +// FileHandler fh; +// FileHandler fh1; +// FileHandler fh2; +// try { +// fh=new FileHandler(params.getBGP4LogFile()); + logParser=LoggerFactory.getLogger("BGP4Parser"); +// logParser.addHandler(fh); +// logParser.setLevel(Level.ALL); +// fh1=new FileHandler(params.getBGP4LogFileClient()); + logClient=LoggerFactory.getLogger("BGP4Client"); +// logClient.addHandler(fh1); +// logClient.setLevel(Level.ALL); +// fh2=new FileHandler(params.getBGP4LogFileServer()); + logServer=LoggerFactory.getLogger("BGP4Peer"); +// logServer.addHandler(fh2); +// logServer.setLevel(Level.ALL); +// +// } catch (Exception e1) { +// e1.printStackTrace(); +// System.exit(1); +// } + logServer.info("Inizializing BGP4 Peer"); + if (iTEDBs!= null) intraTEDBs=iTEDBs; + else intraTEDBs=new Hashtable(); + + if (multiTEDB!= null) multiDomainTEDB = multiTEDB; + else multiDomainTEDB = new MDTEDB(); + + if (params.getLearnTopology().equals("fromXML")){ + //intraTEDBs=new Hashtable(); + //multiDomainTEDB = new MDTEDB(); + //intraTEDBs = FileTEDBUpdater.readMultipleDomainSimpleNetworks(params.getTopologyFile(), null, false,0,Integer.MAX_VALUE, false); + logParser.info("BGPIdentifier: "+params.getBGPIdentifier()); + intraTEDBs = FileTEDBUpdater.readMultipleDomainSimpleNetworks(params.getTopologyFile(), null, false,0,Integer.MAX_VALUE, false, params.getBGPIdentifier()); + + //multiDomainTEDB.initializeFromFile(params.getTopologyFile()); + multiDomainTEDB.initializeFromFile(params.getTopologyFile(), params.getBGPIdentifier()); + + } + // Create Thread executor + //FIXME: Actualizar n�mero de threads que se crean + executor = new ScheduledThreadPoolExecutor(20);//1 para el servidor, 1 para el que lanza y vigila los clientes + // Information about all the sessions of the PCE + if (params.isTest()) { + bgp4SessionsInformation = new BGP4SessionsInformation(params.isTest()); + } + else{ + bgp4SessionsInformation = new BGP4SessionsInformation(); + } + //Create the task to send the topology. It has to be created because you can start sending the topology in the management (wirting): send topology on. + sendTopologyTask = new SendTopology(); + saveTopologyDB= new SaveTopologyinDB(); + if (params.isSaveTopologyDB() == true){ + saveTopologyDB.configure(intraTEDBs, multiDomainTEDB, params.isSaveTopologyDB(), params.getTopologyDBIP().getHostAddress(), params.getTopologyDBport()); + } + + } + + public void setWriteMultiTEDB(MultiDomainTEDB multiTEDB) { + + this.multiDomainTEDB = multiTEDB; + saveTopologyDB.setMultiDomainTEDB(multiTEDB); + } + + /* + //new function from Andrea + public void setWriteMultiAndIntraTEDB(MultiDomainTEDB multiTEDB, Hashtable intraTEDBs) { + + this.multiDomainTEDB = multiTEDB; + this.intraTEDBs = intraTEDBs; + saveTopologyDB.setMultiDomainTEDB(multiTEDB); + saveTopologyDB.setIntraTEDBs(intraTEDBs); + } + */ + + + public void setReadDomainTEDB(DomainTEDB readDomainTEDB) { + //this.readDomainTEDB = readDomainTEDB; + //System.out.println("setReadDomain: readFomainTEDB().getDomainID()="+readDomainTEDB.getDomainID()); + //System.out.println("setReadDomain: readFomainTEDB="+readDomainTEDB.printTopology()); + if(readDomainTEDB.getDomainID() == null) + this.intraTEDBs.put("default", readDomainTEDB); + else + this.intraTEDBs.put(readDomainTEDB.getDomainID().toString(), readDomainTEDB); + } + public void createUpdateDispatcher(){ + //Updater dispatcher + ud = new UpdateDispatcher(multiDomainTEDB,intraTEDBs); + } + + /** + * Function to create the TEDBs of the peer. + * @param nameParametersFile Name of the Parameters File + */ + + + /** + * Start the session for the management of the BGP4. + */ + public void startManagementServer(){ + logServer.debug("Initializing Management Server"); + BGP4ManagementServer bms=new BGP4ManagementServer(params.getBGP4ManagementPort(),multiDomainTEDB,intraTEDBs,bgp4SessionsInformation,sendTopologyTask); + bms.start(); + } + /** + * Function which start the peer as a client which try to establish new sessions with peers. + * It starts a new process for each peer. + */ + public void startClient(){ + logClient.debug("Initializing Session Manager to connect as client"); + if (params.getBGPIdentifier() != null){ + Inet4Address BGPIdentifier=null; + try { + BGPIdentifier = (Inet4Address) InetAddress.getByName(params.getBGPIdentifier()); + } catch (UnknownHostException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return; + } + for (int i =0;i."); + System.exit(1); + } + + } + /** + * Function which starts the peer (listening BGP4 protocol) as a server. + * It starts once the session server manager. + */ + public void startServer(){ + logServer.info("Initializing Session Manager to connect as server"); + Inet4Address localAddress=null; + Inet4Address BGPIdentifier=null; + if (params.getBGPIdentifier() != null){ + try { + localAddress = (Inet4Address) InetAddress.getByName(params.getLocalBGPAddress()); + BGPIdentifier = (Inet4Address) InetAddress.getByName(params.getBGPIdentifier()); + } catch (UnknownHostException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return; + } + if (params.isTest()) { + bgp4SessionServer = new BGP4SessionServerManager(bgp4SessionsInformation, multiDomainTEDB, ud, params.getBGP4Port(), params.getHoldTime(), BGPIdentifier, params.getVersion(), params.getMyAutonomousSystem(), params.isNodelay(), localAddress, params.getKeepAliveTimer(), peersToConnect, params.isTest()); + executor.execute(bgp4SessionServer); + } + else { + bgp4SessionServer = new BGP4SessionServerManager(bgp4SessionsInformation, multiDomainTEDB, ud, params.getBGP4Port(), params.getHoldTime(), BGPIdentifier, params.getVersion(), params.getMyAutonomousSystem(), params.isNodelay(), localAddress, params.getKeepAliveTimer(), peersToConnect); + executor.execute(bgp4SessionServer); + } + + }else{ + logServer.error("ERROR: BGPIdentifier is not configured. To configure: XML file (BGP4Parameters.xml) ."); + System.exit(1); + } + } + + public void startSendTopology(){ + if (params.isTest()) { + sendTopologyTask.configure(intraTEDBs, bgp4SessionsInformation, sendTopology, params.getInstanceID(),params.isSendIntradomainLinks(),this.multiDomainTEDB, params.isTest()); + } + else{ + sendTopologyTask.configure(intraTEDBs, bgp4SessionsInformation, sendTopology, params.getInstanceID(),params.isSendIntradomainLinks(),this.multiDomainTEDB); + } + executor.scheduleWithFixedDelay(sendTopologyTask, 0,params.getSendTopoDelay(), TimeUnit.MILLISECONDS); + } + + + + public void startSaveTopology(){ + //FIXME: ADD param to configure the delay + executor.scheduleWithFixedDelay(saveTopologyDB, 0,5000, TimeUnit.MILLISECONDS); + } + + + public SaveTopologyinDB getSaveTopologyDB() { + return saveTopologyDB; + } + + public void setSaveTopologyDB(SaveTopologyinDB saveTopologyDB) { + this.saveTopologyDB = saveTopologyDB; + } + + public boolean isSaveTopology() { + return saveTopology; + } + + public void setSaveTopology(boolean saveTopology) { + this.saveTopology = saveTopology; + } + + public UpdateDispatcher getUd() { + return ud; + } + + public void setUd(UpdateDispatcher ud) { + this.ud = ud; + } + + public void addSimpleTEDB(SimpleTEDB simpleTEDB, String domainID) { + this.intraTEDBs.put(domainID, simpleTEDB); + } + + public void setSimpleTEDB(SimpleTEDB simpleTEDB) { + if(simpleTEDB.getDomainID() == null) + this.intraTEDBs.put("default", simpleTEDB); + else + this.intraTEDBs.put(simpleTEDB.getDomainID().toString(), simpleTEDB); + } + + + public void stopPeer(){ + executor.shutdown(); + } + public MultiDomainTEDB getMultiDomainTEDB() { + return multiDomainTEDB; + } + + + public Hashtable getIntraTEDBs() { + return intraTEDBs; + } + + public void setIntraTEDBs(Hashtable intraTEDBs) { + this.intraTEDBs = intraTEDBs; + } + + public void setMultiDomainTEDB(MultiDomainTEDB multiDomainTEDB) { + this.multiDomainTEDB = multiDomainTEDB; + } + + + + + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGPPeerMain.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGPPeerMain.java new file mode 100644 index 000000000..97e2702f5 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/BGPPeerMain.java @@ -0,0 +1,37 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.peer; + +public class BGPPeerMain { + + /** + * @param args Command line arguments. First argument, config file. + */ + public static void main(String[] args) { + BGPPeer bgpPeer = new BGPPeer(); + if (args.length != 0) + bgpPeer.configure(args[0]); + else + bgpPeer.configure(); + + //bgpPeer.createTEDB("hola"); //did it in configure + bgpPeer.createUpdateDispatcher(); + bgpPeer.startClient(); + bgpPeer.startServer(); + bgpPeer.startSaveTopology(); + bgpPeer.startManagementServer(); + bgpPeer.startSendTopology(); + } +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/SaveTopologyinDB.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/SaveTopologyinDB.java new file mode 100644 index 000000000..bd27bb87a --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/peer/SaveTopologyinDB.java @@ -0,0 +1,300 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +package eu.teraflow.tid.bgp4Peer.peer; + +import java.net.Inet4Address; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import eu.teraflow.tid.tedb.DatabaseControlSimplifiedLSA; +import eu.teraflow.tid.tedb.DomainTEDB; +import eu.teraflow.tid.tedb.InterDomainEdge; +import eu.teraflow.tid.tedb.IntraDomainEdge; +import eu.teraflow.tid.tedb.MultiDomainTEDB; +import eu.teraflow.tid.tedb.TEDB; +import eu.teraflow.tid.tedb.TE_Information; +import redis.clients.jedis.Jedis; + +/** + * Class to save periodically the topology. It sends the topology to the active BGP4 sessions. + * @author pac + * + */ +public class SaveTopologyinDB implements Runnable { + + //FIXME: Configure from file + private Jedis jedis; + private String host="localhost"; + private int port=6379; + + //TEDBs + private Hashtable intraTEDBs; + + // Multi-domain TEDB to redistribute Multi-domain Topology + private MultiDomainTEDB multiDomainTEDB; + + private boolean writeTopology; + + private Logger log; + + + public SaveTopologyinDB(){ + log = LoggerFactory.getLogger("BGP4Peer"); + jedis = new Jedis(host,port); + } + + public void configure( Hashtable intraTEDBs,MultiDomainTEDB multiTED, boolean writeTopology, String host, int port){ + this.intraTEDBs=intraTEDBs; + this.writeTopology=writeTopology; + this.multiDomainTEDB=multiTED; + //rdh.setHost(host); + //rdh.setPort(port); + + + if (writeTopology){ + jedis = new Jedis(host,port); + jedis.connect(); + } + } + + /** + * Function to send the topology database. + */ + + + public void run(){ + try { + if (writeTopology){ + log.info("Going to save Topology in Redis DB"); + if (jedis==null){ + jedis = new Jedis(host,port); + jedis.connect(); + }else if (jedis.isConnected()==false){ + jedis.connect(); + } + if (multiDomainTEDB!=null){ + log.info("save Multi-Domain TEDB"); + writeLinkDBInter( multiDomainTEDB.getInterDomainLinks()); + } + else { + log.info("save form TEDB"); + Enumeration iter = intraTEDBs.elements(); + while (iter.hasMoreElements()){ + writeLinkDBInter( iter.nextElement().getInterDomainLinks()); + } + } + + log.info("sendIntraDomainLinks activated"); + Enumeration iter = intraTEDBs.keys(); + while (iter.hasMoreElements()){ + String domainID = iter.nextElement(); + log.info("Sending TED from domain "+domainID); + DomainTEDB ted=(DomainTEDB)intraTEDBs.get(domainID); + //writeLinkDB( ted.getNetworkGraph().edgeSet(),domainID); + writeLinkDB(ted.getIntraDomainLinks(),domainID); + } + + + } + }catch (Exception e) { + e.printStackTrace(); + log.error("PROBLEM Writing TOPOLOGY: "+e.toString()); + } + + } + + /** + * This function write a BGP4 update message in Data Base for each link in the list + * @param intradomainLinks + */ + private void writeLinkDB(Set intradomainLinks, String domainID){ + + Iterator edgeIt = intradomainLinks.iterator(); + + while (edgeIt.hasNext()){ + + IntraDomainEdge edge = edgeIt.next(); + + DatabaseControlSimplifiedLSA dcsl =createSimplifiedLSA(edge); + String jsonLSA = dcsl.logJsonSimplifiedLSA(); + + if (jedis == null) + log.info("JEDIS IS NULL"); + + String ret = jedis.set("LSA:"+dcsl.getAdvertisingRouter().getHostAddress()+":"+dcsl.getLinkId().getHostAddress(), jsonLSA); + } + + } + + private DatabaseControlSimplifiedLSA createSimplifiedLSA(IntraDomainEdge edge){ + DatabaseControlSimplifiedLSA dcsl = new DatabaseControlSimplifiedLSA(); + + //Inet4Address source = (Inet4Address)edge.getSrc_router_id(); + //Inet4Address dst = (Inet4Address)edge.getDst_router_id(); + + Inet4Address source = (Inet4Address)edge.getSource(); + dcsl.setAdvertisingRouter(source); + Inet4Address dst = (Inet4Address)edge.getTarget(); + dcsl.setLinkId(dst); + + TE_Information te_info = ((IntraDomainEdge) edge).getTE_info(); + + if (te_info != null){ + + if (te_info.getLinkLocalRemoteIdentifiers() != null){ + dcsl.linkLocalIdentifier = te_info.getLinkLocalRemoteIdentifiers().getLinkLocalIdentifier(); + } + + if (te_info.getLinkLocalRemoteIdentifiers() != null){ + dcsl.linkRemoteIdentifier = te_info.getLinkLocalRemoteIdentifiers().getLinkRemoteIdentifier(); + } + + if (te_info.getMaximumBandwidth() != null) { + dcsl.maximumBandwidth = te_info.getMaximumBandwidth().getMaximumBandwidth(); + } + + if (te_info.getUnreservedBandwidth() != null) { + dcsl.unreservedBandwidth = te_info.getUnreservedBandwidth().getUnreservedBandwidth()[0]; + } + + if (te_info.getMaximumReservableBandwidth() != null) + dcsl.maximumReservableBandwidth = te_info.getMaximumReservableBandwidth().getMaximumReservableBandwidth(); + + String ret = ""; + + if (te_info.getAvailableLabels() != null){ + + if (te_info.getAvailableLabels().getLabelSet() != null){ + + ret=ret+" Bitmap: {"; + + for (int i=0;i interdomainLinks){ + + Iterator edgeIt = interdomainLinks.iterator(); + + while (edgeIt.hasNext()){ + + InterDomainEdge edge = edgeIt.next(); + + DatabaseControlSimplifiedLSA dcsl =createSimplifiedLSAInter(edge); + String jsonLSA = dcsl.logJsonSimplifiedLSA(); + //rdh.write("LSA:"+dcsl.getAdvertisingRouter().getHostAddress()+":"+dcsl.getLinkId().getHostAddress(),jsonLSA); + String ret = jedis.set("LSA:"+dcsl.getAdvertisingRouter().getHostAddress()+":"+dcsl.getLinkId().getHostAddress(), jsonLSA); + } + + } + + private DatabaseControlSimplifiedLSA createSimplifiedLSAInter(InterDomainEdge edge){ + DatabaseControlSimplifiedLSA dcsl = new DatabaseControlSimplifiedLSA(); + + //Inet4Address source = (Inet4Address)edge.getSrc_router_id(); + //Inet4Address dst = (Inet4Address)edge.getDst_router_id(); + + Inet4Address source = (Inet4Address)edge.getSource(); + dcsl.setAdvertisingRouter(source); + Inet4Address dst = (Inet4Address)edge.getTarget(); + dcsl.setLinkId(dst); + + TE_Information te_info = ((InterDomainEdge) edge).getTE_info(); + + if (te_info != null){ + + if (te_info.getLinkLocalRemoteIdentifiers() != null){ + dcsl.linkLocalIdentifier = te_info.getLinkLocalRemoteIdentifiers().getLinkLocalIdentifier(); + } + + if (te_info.getLinkLocalRemoteIdentifiers() != null){ + dcsl.linkRemoteIdentifier = te_info.getLinkLocalRemoteIdentifiers().getLinkRemoteIdentifier(); + } + + if (te_info.getMaximumBandwidth() != null) { + dcsl.maximumBandwidth = te_info.getMaximumBandwidth().getMaximumBandwidth(); + } + + if (te_info.getUnreservedBandwidth() != null) { + dcsl.unreservedBandwidth = te_info.getUnreservedBandwidth().getUnreservedBandwidth()[0]; + } + + if (te_info.getMaximumReservableBandwidth() != null) + dcsl.maximumReservableBandwidth = te_info.getMaximumReservableBandwidth().getMaximumReservableBandwidth(); + + String ret = ""; + + if (te_info.getAvailableLabels() != null){ + + if (te_info.getAvailableLabels().getLabelSet() != null){ + + ret=ret+" Bitmap: {"; + + for (int i=0;i intraTEDBs; + + // Multi-domain TEDB to redistribute Multi-domain Topology + private MultiDomainTEDB multiDomainTEDB; + + private boolean sendTopology; + private boolean isTest=false; + private BGP4SessionsInformation bgp4SessionsInformation; + private Logger log; + private int instanceId=1; + private boolean sendIntraDomainLinks=false; + + private boolean send4AS=false; + + + + + private Inet4Address localBGPLSIdentifer; + private Inet4Address localAreaID; + + public SendTopology(){ + log = LoggerFactory.getLogger("BGP4Peer"); + } + + public void configure( Hashtable intraTEDBs,BGP4SessionsInformation bgp4SessionsInformation,boolean sendTopology,int instanceId,boolean sendIntraDomainLinks, MultiDomainTEDB multiTED){ + this.intraTEDBs=intraTEDBs; + this.bgp4SessionsInformation=bgp4SessionsInformation; + this.sendTopology= sendTopology; + this.instanceId = instanceId; + this.sendIntraDomainLinks=sendIntraDomainLinks; + this.multiDomainTEDB=multiTED; + try { + this.localAreaID=(Inet4Address)Inet4Address.getByName("0.0.0.0"); + this.localBGPLSIdentifer=(Inet4Address)Inet4Address.getByName("1.1.1.1"); + } catch (UnknownHostException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + + public void configure( Hashtable intraTEDBs,BGP4SessionsInformation bgp4SessionsInformation,boolean sendTopology,int instanceId,boolean sendIntraDomainLinks, MultiDomainTEDB multiTED, boolean test){ + this.intraTEDBs=intraTEDBs; + this.bgp4SessionsInformation=bgp4SessionsInformation; + this.sendTopology= sendTopology; + this.instanceId = instanceId; + this.sendIntraDomainLinks=sendIntraDomainLinks; + this.multiDomainTEDB=multiTED; + this.isTest=test; + try { + this.localAreaID=(Inet4Address)Inet4Address.getByName("0.0.0.0"); + this.localBGPLSIdentifer=(Inet4Address)Inet4Address.getByName("1.1.1.1"); + } catch (UnknownHostException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + /** + * Function to send the topology database. + */ + + + public void run(){ + try { + if (sendTopology){ + if (!(bgp4SessionsInformation.getSessionList().isEmpty())){ + if (multiDomainTEDB!=null){ + log.debug("Sending Multi-Domain TEDB"); + sendLinkNLRI( multiDomainTEDB.getInterDomainLinks()); + } + else { + log.debug("Sending from TEDB"); + Enumeration iter = intraTEDBs.elements(); + while (iter.hasMoreElements()){ + sendLinkNLRI( iter.nextElement().getInterDomainLinks()); + } + } + + if (sendIntraDomainLinks){//Intradomain Links + log.debug("sendIntraDomainLinks activated"); + Enumeration iter = intraTEDBs.keys(); + while (iter.hasMoreElements()){ + String domainID = iter.nextElement(); + //Andrea + log.debug("Sending TED from domain "+domainID); + + TEDB ted=intraTEDBs.get(domainID); + if (ted instanceof DomainTEDB) { + sendLinkNLRI( ((DomainTEDB)ted).getIntraDomainLinks(),domainID); + //log.info(" XXXX ted.getNodeTable():"+ted.getNodeTable()); + sendNodeNLRI( ((DomainTEDB)ted).getIntraDomainLinksvertexSet(), ((DomainTEDB)ted).getNodeTable()); + if (((DomainTEDB)ted).getItResources()!=null){ + sendITNodeNLRI( domainID, ((DomainTEDB)ted).getItResources()); + } + + } + + + + } + + } + + } + } + }catch (Exception e) { + e.printStackTrace(); + log.error("PROBLEM SENDING TOPOLOGY: "+e.toString()); + } + + } + /** + * This function sends a BGP4 update message (encoded in a NodeNLRI) for each node in the set + * @param vertexIt + */ + private void sendNodeNLRI(Set vertexSet, Hashtable NodeTable){ + Iterator vertexIt = vertexSet.iterator(); + //Enviamos primero los nodos. Un Node NLRI por cada nodo. + while (vertexIt.hasNext()){ + Inet4Address node=null; + Object v = vertexIt.next(); + if( v instanceof eu.teraflow.tid.tedb.elements.Node){ + try { + node = (Inet4Address)Inet4Address.getByName(((eu.teraflow.tid.tedb.elements.Node)v).getAddress().get(0)); + } catch (UnknownHostException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + }else{ + node = (Inet4Address)v; + } + + + //log.info(" XXXX node: "+ node); + Node_Info node_info = NodeTable.get(node); + //log.info(" XXXX node_info: "+ node_info); + if (node_info!=null){ + log.debug("Sending node: ("+node+")"); + //Mandamos NodeNLRI + BGP4Update update = createMsgUpdateNodeNLRI(node_info); + sendMessage(update); + }else { + log.debug("Node "+node+ " HAS NO node_info in NodeTable"); + } + + + } + } + + /** + * This function sends a BGP4 update message (encoded in a ITNodeNLRI) for each node in the set + * @param vertexIt + */ + + + private void sendITNodeNLRI(String domainID, IT_Resources itResources){ + //Andrea + log.debug("Sending IT REsources"); + BGP4Update update = createMsgUpdateITNodeNLRI(domainID, itResources); + sendMessage(update); +// Iterator vertexIt = vertexSet.iterator(); +// //Enviamos primero los nodos. Un Node NLRI por cada nodo. +// while (vertexIt.hasNext()){ +// Inet4Address node = (Inet4Address)vertexIt.next(); +// //log.info(" XXXX node: "+ node); +// Node_Info node_info = NodeTable.get(node); +// //log.info(" XXXX node_info: "+ node_info); +// if (node_info!=null){ +// log.debug("Sending node: ("+node+")"); +// //Mandamos NodeNLRI +// BGP4Update update = createMsgUpdateNodeNLRI(node_info); +// sendMessage(update); +// }else { +// log.error("Node "+node+ " HAS NO node_info in NodeTable"); +// } +// +// +// } + } + + /** + * This function sends a BGP4 update message (encoded in a LinkNLRI) for each link in the list + * @param interdomainLinks + */ + private void sendLinkNLRI(LinkedList interdomainLinks){ + if (true){ + int lanID = 1; ///INVENTADOO + ArrayList addressList = new ArrayList(); + Iterator edgeIt = interdomainLinks.iterator(); + while (edgeIt.hasNext()){ + + InterDomainEdge edge = edgeIt.next(); + Inet4Address source = (Inet4Address)edge.getSrc_router_id(); + Inet4Address dst = (Inet4Address)edge.getDst_router_id(); + log.debug("Sending ID edge: ("+source.toString() +":"+((InterDomainEdge) edge).getSrc_if_id()+","+dst.toString()+")"); + addressList = new ArrayList(); + addressList.add(0,source); + addressList.add(1,dst); + + + + //Link Local Remote Identifiers + ArrayList localRemoteIfList =null; + localRemoteIfList= new ArrayList (); + localRemoteIfList.add(0,((InterDomainEdge) edge).getSrc_if_id());//te_info.getLinkLocalRemoteIdentifiers().getLinkLocalIdentifier()); + localRemoteIfList.add(1,((InterDomainEdge) edge).getDst_if_id());//te_info.getLinkLocalRemoteIdentifiers().getLinkRemoteIdentifier()); + + + ArrayList domainList = new ArrayList(2); + //FIXME: chequear + TE_Information te_info = ((InterDomainEdge) edge).getTE_info(); + + domainList.add(((Inet4Address)edge.getDomain_src_router()).getHostAddress().toString()); + //System.out.println("SRC Domain is "+((Inet4Address)edge.getDomain_src_router()).getHostAddress().toString() ); + domainList.add( ((Inet4Address)edge.getDomain_dst_router()).getHostAddress().toString()); + log.debug("SRC Domain is "+(Inet4Address)edge.getDomain_dst_router()); + BGP4Update update = createMsgUpdateLinkNLRI(addressList,localRemoteIfList, lanID, domainList, false, te_info); + update.setLearntFrom(edge.getLearntFrom()); + log.debug("Update message Created"); + sendMessage(update); + } + } + + } + /** + * This function sends a BGP4 update message (encoded in a LinkNLRI) for each link in the set + * @param edgeIt + */ + private void sendLinkNLRI(Set edgeSet, String domainID){ + int lanID = 1; ///INVENTADOO + ArrayList addressList = new ArrayList(); + Iterator edgeIt = edgeSet.iterator(); + while (edgeIt.hasNext()){ + + IntraDomainEdge edge = edgeIt.next(); + Inet4Address source=null; + if(edge.getSource() instanceof eu.teraflow.tid.tedb.elements.Node){ + try { + source=(Inet4Address)Inet4Address.getByName(((eu.teraflow.tid.tedb.elements.Node)edge.getSource()).getAddress().get(0)); + } catch (UnknownHostException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + }else{ + source = (Inet4Address)edge.getSource(); + } + + Inet4Address dst=null; + if(edge.getTarget() instanceof eu.teraflow.tid.tedb.elements.Node){ + try { + dst=(Inet4Address)Inet4Address.getByName(((eu.teraflow.tid.tedb.elements.Node)edge.getTarget()).getAddress().get(0)); + } catch (UnknownHostException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + }else{ + dst = (Inet4Address)edge.getTarget(); + } + log.debug("Sending: ("+source.toString() +","+dst.toString()+")"); + addressList = new ArrayList(); + addressList.add(0,source); + addressList.add(1,dst); + //Link Local Remote Identifiers + ArrayList localRemoteIfList =null; + localRemoteIfList= new ArrayList (); + localRemoteIfList.add(0,((IntraDomainEdge) edge).getSrc_if_id());//te_info.getLinkLocalRemoteIdentifiers().getLinkLocalIdentifier()); + localRemoteIfList.add(1,((IntraDomainEdge) edge).getDst_if_id());//te_info.getLinkLocalRemoteIdentifiers().getLinkRemoteIdentifier()); + + //MPLS + float maximumBandwidth = 0; + float[] unreservedBandwidth = null; + float maximumReservableBandwidth = 0; + int undirLinkDelay = 0; + int metric = 0; + long te_metric =0; + + //GMPLS + AvailableLabels availableLabels = null; + MF_OTPAttribTLV mfOTP = null; + + + TE_Information te_info = ((IntraDomainEdge) edge).getTE_info(); + + ArrayList domainList = new ArrayList(2); + domainList.add(domainID); + domainList.add(domainID); + BGP4Update update = createMsgUpdateLinkNLRI(addressList,localRemoteIfList, lanID, domainList, true, te_info); + update.setLearntFrom(edge.getLearntFrom()); + sendMessage(update); + + } + + } + /** + * Function to send a BGP4 update message to the connected peers. + * @param update + */ + private void sendMessage (BGP4Update update){ + + Enumeration sessions = bgp4SessionsInformation.getSessionList().elements(); + + log.debug("Sending a BGP4 update message:"+update.toString()); + while (sessions.hasMoreElements()){ + GenericBGP4Session session = sessions.nextElement(); + if (session==null) { + log.error("SESSION NULL"); + }else { + if (session.getSendTo()) { + String destination = session.getRemotePeerIP().getHostAddress(); + log.debug("BGP4 Update learnt from:" + update.getLearntFrom()); + if (isTest){ + log.debug("Sending BGP4 update to:" + destination+" with no check on the ID since it is test"); + session.sendBGP4Message(update); + } + else{ + try { + if ((update.getLearntFrom() != null) && (update.getLearntFrom().contains("/"))) { + //log.info(update.getLearntFrom().substring(1)); + if (!destination.equals(update.getLearntFrom().substring(1))) { + //log.info("id da getLearnt "+ update.getLearntFrom()); + log.debug("Sending update to destination " + destination + " for info learnt from " + update.getLearntFrom().substring(1)); + log.debug("Sending BGP4 update to:" + destination); + session.sendBGP4Message(update); + + } else + log.debug("destination " + destination + " and source of information " + update.getLearntFrom().substring(1) + " are equal"); + + + } + else{ + if (!destination.equals(update.getLearntFrom())) { + //log.info("id da getLearnt "+ update.getLearntFrom()); + log.debug("Sending update to destination " + destination + " for info learnt from " + update.getLearntFrom()); + log.debug("Sending BGP4 update to:" + destination); + session.sendBGP4Message(update); + } else + log.debug("destination " + destination + " and source of information " + update.getLearntFrom() + " are equal"); + } + } + catch (Exception e){ + e.printStackTrace(); + } + } + } + } + + } + } + /** + * This function create a BGP4 Message with NodeNLRI field + + * @param node_info + */ + private BGP4Update createMsgUpdateNodeNLRI(Node_Info node_info){ + try{ + + + BGP4Update update= new BGP4Update(); + //Path Attributes + ArrayList pathAttributes = update.getPathAttributes(); + //Origin + OriginAttribute or = new OriginAttribute(); + or.setValue(PathAttributesTypeCode.PATH_ATTRIBUTE_ORIGIN_IGP); + pathAttributes.add(or); + //AS_PATH + if (send4AS==true) { + AS_Path_Attribute as_path = new AS_Path_Attribute(); + AS_Path_Segment as_path_seg = new AS_Path_Segment(); + long[] segs = new long[1]; + segs[0] = 65522; + as_path_seg.set4Segments(segs); + as_path.getAsPathSegments().add(as_path_seg); + pathAttributes.add(as_path); + } + else { + AS_Path_Attribute as_path = new AS_Path_Attribute(); + AS_Path_Segment as_path_seg = new AS_Path_Segment(); + int[] segs = new int[1]; + segs[0] = 65522; + as_path_seg.setSegments(segs); + as_path.getAsPathSegments().add(as_path_seg); + pathAttributes.add(as_path); + } + + //Node Attribute + + LinkStateAttribute linkStateAttribute = new LinkStateAttribute(); + boolean linkStateNeeded=false; + + if (node_info.getSid()!=0){ + int sid = node_info.getSid(); + SidLabelNodeAttribTLV sidLabelTLV = new SidLabelNodeAttribTLV(); + sidLabelTLV.setSid(sid); + linkStateAttribute.setSidLabelTLV(sidLabelTLV); + linkStateNeeded=true; + } + + if (linkStateNeeded){ + log.debug("Node Attribute added...."); + pathAttributes.add(linkStateAttribute); + } + + //NLRI + NodeNLRI nodeNLRI = new NodeNLRI(); + nodeNLRI.setProtocolID(ProtocolIDCodes.Unknown_Protocol_ID); + nodeNLRI.setRoutingUniverseIdentifier(identifier); + LocalNodeDescriptorsTLV localNodeDescriptors = new LocalNodeDescriptorsTLV(); + + //igp router id + if(node_info.getIpv4Address()!=null){ + IGPRouterIDNodeDescriptorSubTLV igpRouterIDLNSubTLV = new IGPRouterIDNodeDescriptorSubTLV(); + igpRouterIDLNSubTLV.setIpv4AddressOSPF(node_info.getIpv4Address()); + igpRouterIDLNSubTLV.setIGP_router_id_type(IGPRouterIDNodeDescriptorSubTLV.IGP_ROUTER_ID_TYPE_OSPF_NON_PSEUDO); + localNodeDescriptors.setIGPRouterID(igpRouterIDLNSubTLV); + + } + + //as number + if(node_info.getAs_number()!=null){ + AutonomousSystemNodeDescriptorSubTLV asNodeDescrSubTLV = new AutonomousSystemNodeDescriptorSubTLV(); + asNodeDescrSubTLV.setAS_ID(node_info.getAs_number()); + localNodeDescriptors.setAutonomousSystemSubTLV(asNodeDescrSubTLV); + } + //Complete Dummy TLVs + BGPLSIdentifierNodeDescriptorSubTLV bGPLSIDSubTLV =new BGPLSIdentifierNodeDescriptorSubTLV(); + bGPLSIDSubTLV.setBGPLS_ID(this.localBGPLSIdentifer); + localNodeDescriptors.setBGPLSIDSubTLV(bGPLSIDSubTLV); + AreaIDNodeDescriptorSubTLV areaID = new AreaIDNodeDescriptorSubTLV(); + areaID.setAREA_ID(this.localAreaID); + localNodeDescriptors.setAreaID(areaID); + + nodeNLRI.setLocalNodeDescriptors(localNodeDescriptors); + BGP_LS_MP_Reach_Attribute ra= new BGP_LS_MP_Reach_Attribute(); + ra.setLsNLRI(nodeNLRI); + pathAttributes.add(ra); + update.setLearntFrom(node_info.getLearntFrom()); + return update; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + } + + /** + * This function create a BGP4 Message with NodeNLRI field + * @param addressList + * @param node_info + */ + private BGP4Update createMsgUpdateITNodeNLRI(String domainID, IT_Resources itResources){ + try{ + + BGP4Update update= new BGP4Update(); + //Path Attributes + ArrayList pathAttributes = update.getPathAttributes(); + //Origin + OriginAttribute or = new OriginAttribute(); + or.setValue(PathAttributesTypeCode.PATH_ATTRIBUTE_ORIGIN_IGP); + pathAttributes.add(or); + + //AS_PATH + if (send4AS==true) { + AS_Path_Attribute as_path = new AS_Path_Attribute(); + AS_Path_Segment as_path_seg = new AS_Path_Segment(); + long[] segs = new long[1]; + segs[0] = 65522; + as_path_seg.set4Segments(segs); + as_path.getAsPathSegments().add(as_path_seg); + pathAttributes.add(as_path); + } + else { + AS_Path_Attribute as_path = new AS_Path_Attribute(); + AS_Path_Segment as_path_seg = new AS_Path_Segment(); + int[] segs = new int[1]; + segs[0] = 65522; + as_path_seg.setSegments(segs); + as_path.getAsPathSegments().add(as_path_seg); + pathAttributes.add(as_path); + } + + + + + //NLRI + ITNodeNLRI itNodeNLRI = new ITNodeNLRI(); + itNodeNLRI.setNodeId(domainID); + itNodeNLRI.setControllerIT(itResources.getControllerIT()); + itNodeNLRI.setCpu(itResources.getCpu()); + itNodeNLRI.setMem(itResources.getMem()); + itNodeNLRI.setStorage(itResources.getStorage()); + update.setLearntFrom(itResources.getLearntFrom()); + log.info("Creating IT Update related to domain "+domainID+" learnt from "+itResources.getLearntFrom()); + LocalNodeDescriptorsTLV localNodeDescriptors = new LocalNodeDescriptorsTLV(); + + //Complete Dummy TLVs + BGPLSIdentifierNodeDescriptorSubTLV bGPLSIDSubTLV =new BGPLSIdentifierNodeDescriptorSubTLV(); + bGPLSIDSubTLV.setBGPLS_ID(this.localBGPLSIdentifer); + localNodeDescriptors.setBGPLSIDSubTLV(bGPLSIDSubTLV); + AreaIDNodeDescriptorSubTLV areaID = new AreaIDNodeDescriptorSubTLV(); + areaID.setAREA_ID(this.localAreaID); + localNodeDescriptors.setAreaID(areaID); + + //itNodeNLRI.setLocalNodeDescriptors(localNodeDescriptors); + BGP_LS_MP_Reach_Attribute ra= new BGP_LS_MP_Reach_Attribute(); + ra.setLsNLRI(itNodeNLRI); + pathAttributes.add(ra); + return update; + + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + } + + /** + * Function to create a BGP4 update message with a link NRLI field. To send the links. + * + * @param addressList + * @param addressInterfaceList + * @param localRemoteIfList + * @param lanID + * @param maximumBandwidth + * @param unreservedBandwidth + * @param maximumReservableBandwidth + * @param availableLabels + * @param metric + * @param domainList + * @param intradomain + * @param linkDelay + */ + private BGP4Update createMsgUpdateLinkNLRI(ArrayList addressList,ArrayList localRemoteIfList,int lanID, ArrayList domainList, boolean intradomain, TE_Information te_info ){ + BGP4Update update= new BGP4Update(); + //1. Path Attributes + ArrayList pathAttributes = update.getPathAttributes(); + //1.1. Origin + OriginAttribute or = new OriginAttribute(); + if (intradomain) + or.setValue(PathAttributesTypeCode.PATH_ATTRIBUTE_ORIGIN_IGP); + else + or.setValue(PathAttributesTypeCode.PATH_ATTRIBUTE_ORIGIN_EGP); + pathAttributes.add(or); + ///Andreaaaaa + //update.setLearntFrom("192.168.0.1"); + //1.2. AS-PATH + + if (send4AS==true) { + AS_Path_Attribute as_path = new AS_Path_Attribute(); + AS_Path_Segment as_path_seg = new AS_Path_Segment(); + long[] segs = new long[1]; + segs[0] = 65522; + as_path_seg.set4Segments(segs); + as_path.getAsPathSegments().add(as_path_seg); + pathAttributes.add(as_path); + } + else { + AS_Path_Attribute as_path = new AS_Path_Attribute(); + AS_Path_Segment as_path_seg = new AS_Path_Segment(); + int[] segs = new int[1]; + segs[0] = 65522; + as_path_seg.setSegments(segs); + as_path.getAsPathSegments().add(as_path_seg); + pathAttributes.add(as_path); + } + + + //1.2. LINK-STATE + //MPLS + float maximumBandwidth = 0; + float[] unreservedBandwidth = null; + float maximumReservableBandwidth = 0; + + //GMPLS + AvailableLabels availableLabels = null; + MF_OTPAttribTLV mfOTP = null; + + int metric = 0; + int te_metric = 0; + + + if (te_info != null){ + if (te_info.getLinkLocalRemoteIdentifiers() != null){ + + } + //MPLS + if (te_info.getMaximumBandwidth() != null) { + maximumBandwidth = te_info.getMaximumBandwidth().getMaximumBandwidth(); + } + if (te_info.getUnreservedBandwidth() != null) + unreservedBandwidth = te_info.getUnreservedBandwidth().getUnreservedBandwidth(); + if (te_info.getMaximumReservableBandwidth() != null) + maximumReservableBandwidth = te_info.getMaximumReservableBandwidth().getMaximumReservableBandwidth(); + //GMPLS + if (te_info.getAvailableLabels() != null) + availableLabels = te_info.getAvailableLabels(); + if(te_info.getDefaultTEMetric()!=null){ + metric = (int) te_info.getDefaultTEMetric().getLinkMetric(); + log.debug("Metric en el metodo sendLinkNLRI es: " + metric); + } + if(te_info.getTrafficEngineeringMetric()!=null){ + te_metric = (int) te_info.getTrafficEngineeringMetric().getLinkMetric() ; + log.debug("Metric en el metodo sendLinkNLRI es: " + metric); + } + if(te_info.getMfOTF()!=null){ + mfOTP = te_info.getMfOTF(); + } + + }else{ + log.debug("TE_Info es null"); + } + + + boolean linkStateNeeded = false; + LinkStateAttribute linkStateAttribute = new LinkStateAttribute(); + //1.2.1. MaxReservableBandwidth + if (maximumReservableBandwidth != 0){ + MaxReservableBandwidthLinkAttribTLV maxReservableBandwidthTLV = new MaxReservableBandwidthLinkAttribTLV(); + maxReservableBandwidthTLV.setMaximumReservableBandwidth(maximumReservableBandwidth); + linkStateAttribute.setMaxReservableBandwidthTLV(maxReservableBandwidthTLV); + linkStateNeeded=true; + } + //1.2.2. maxBandwidth + if (maximumBandwidth != 0){ + MaximumLinkBandwidthLinkAttribTLV maximumLinkBandwidthTLV = new MaximumLinkBandwidthLinkAttribTLV(); + maximumLinkBandwidthTLV.setMaximumBandwidth(maximumBandwidth); + linkStateAttribute.setMaximumLinkBandwidthTLV(maximumLinkBandwidthTLV); + linkStateNeeded=true; + } + //1.2.3. unreservedBandwidth + if (unreservedBandwidth != null){ + UnreservedBandwidthLinkAttribTLV unreservedBandwidthTLV = new UnreservedBandwidthLinkAttribTLV(); + unreservedBandwidthTLV.setUnreservedBandwidth(unreservedBandwidth); + linkStateAttribute.setUnreservedBandwidthTLV(unreservedBandwidthTLV); + linkStateNeeded=true; + } + //1.2.4. AvailableLabels + if (availableLabels != null){ + log.debug("Available labels fields: "+availableLabels.getLabelSet().getNumLabels()); + AvailableLabels al = new AvailableLabels(); + + BitmapLabelSet bl = new BitmapLabelSet(); + bl.setBytesBitmap(((BitmapLabelSet)availableLabels.getLabelSet()).getBytesBitMap()); + bl.setNumLabels(availableLabels.getLabelSet().getNumLabels()); + bl.setDwdmWavelengthLabel(((BitmapLabelSet)availableLabels.getLabelSet()).getDwdmWavelengthLabel()); + + bl.setBytesBitmapReserved(((BitmapLabelSet)availableLabels.getLabelSet()).getBytesBitmapReserved()); + + al.setLabelSet(bl); + + log.debug("Campo BytesBitmap: "+Integer.toHexString(((int)bl.getBytesBitMap()[0])&0xFF)); + log.debug("Campo DwdmWavelengthLabel: "+bl.getDwdmWavelengthLabel()); + if (bl.getBytesBitmapReserved()!=null){ + log.debug("Campo BytesBitmapReserved: "+bl.getBytesBitmapReserved()[0]); + } + linkStateAttribute.setAvailableLabels(al); + + linkStateNeeded=true; + } + //1.2.5 metric +// if (metric != 0){ +// DefaultTEMetricLinkAttribTLV defaultMetric = new DefaultTEMetricLinkAttribTLV(); +// defaultMetric.setLinkMetric(metric); +// log.info("Metric en el metodo createMsgUpdateLinkNLRI es: " + metric); +// linkStateAttribute.setTEMetricTLV(defaultMetric); +// linkStateNeeded=true; +// } + + if (te_metric != 0){ + DefaultTEMetricLinkAttribTLV defaultMetric = new DefaultTEMetricLinkAttribTLV(); + //defaultMetric.setLinkMetric(metric); + defaultMetric.setLinkMetric(te_metric); + log.debug("Metric en el metodo createMsgUpdateLinkNLRI es: " + te_metric); + linkStateAttribute.setTEMetricTLV(defaultMetric); + linkStateNeeded=true; + } + + //1.2.6 MF_OPT + if (mfOTP != null){ + MF_OTPAttribTLV mfOTPTLV = mfOTP.duplicate(); + log.debug("SENDING MFOTP OSCAR"); + linkStateAttribute.setMF_OTP_ATLV(mfOTPTLV); + linkStateNeeded=true; + } + + if (linkStateNeeded){ + pathAttributes.add(linkStateAttribute); + } + //2. NLRI + LinkNLRI linkNLRI = new LinkNLRI(); + linkNLRI.setProtocolID(ProtocolIDCodes.Unknown_Protocol_ID); + linkNLRI.setIdentifier(instanceId); + + //2.1. Local Y Remote Descriptors + LocalNodeDescriptorsTLV localNodeDescriptors = new LocalNodeDescriptorsTLV(); + RemoteNodeDescriptorsTLV remoteNodeDescriptors = new RemoteNodeDescriptorsTLV(); + + //2.1.1. IPv4 + IGPRouterIDNodeDescriptorSubTLV igpRouterIDLNSubTLV = new IGPRouterIDNodeDescriptorSubTLV(); + igpRouterIDLNSubTLV.setIpv4AddressOSPF(addressList.get(0)); + igpRouterIDLNSubTLV.setIGP_router_id_type(IGPRouterIDNodeDescriptorSubTLV.IGP_ROUTER_ID_TYPE_OSPF_NON_PSEUDO); + localNodeDescriptors.setIGPRouterID(igpRouterIDLNSubTLV); + //Complete Dummy TLVs + BGPLSIdentifierNodeDescriptorSubTLV bGPLSIDSubTLV =new BGPLSIdentifierNodeDescriptorSubTLV(); + bGPLSIDSubTLV.setBGPLS_ID(this.localBGPLSIdentifer); + localNodeDescriptors.setBGPLSIDSubTLV(bGPLSIDSubTLV); + AreaIDNodeDescriptorSubTLV areaID = new AreaIDNodeDescriptorSubTLV(); + areaID.setAREA_ID(this.localAreaID); + localNodeDescriptors.setAreaID(areaID); + + IGPRouterIDNodeDescriptorSubTLV igpRouterIDDNSubTLV = new IGPRouterIDNodeDescriptorSubTLV(); + igpRouterIDDNSubTLV.setIpv4AddressOSPF(addressList.get(1)); + igpRouterIDDNSubTLV.setIGP_router_id_type(IGPRouterIDNodeDescriptorSubTLV.IGP_ROUTER_ID_TYPE_OSPF_NON_PSEUDO); + remoteNodeDescriptors.setIGPRouterID(igpRouterIDDNSubTLV); + //2.1.2. AS + if (domainList != null){ + AutonomousSystemNodeDescriptorSubTLV as_local = new AutonomousSystemNodeDescriptorSubTLV(); + try { + as_local.setAS_ID((Inet4Address) Inet4Address.getByName(domainList.get(0))); + localNodeDescriptors.setAutonomousSystemSubTLV(as_local); + AutonomousSystemNodeDescriptorSubTLV as_remote = new AutonomousSystemNodeDescriptorSubTLV(); + as_remote.setAS_ID((Inet4Address) Inet4Address.getByName(domainList.get(1))); + remoteNodeDescriptors.setAutonomousSystemSubTLV(as_remote); + } catch (UnknownHostException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + //Complete Dummy TLVs + remoteNodeDescriptors.setBGPLSIDSubTLV(bGPLSIDSubTLV); + remoteNodeDescriptors.setAreaID(areaID); + + linkNLRI.setLocalNodeDescriptors(localNodeDescriptors); + linkNLRI.setRemoteNodeDescriptorsTLV(remoteNodeDescriptors); + + //2.2. Link NLRI TLVs + //2.2.1. Ipv4 interface and neighbour address + IPv4InterfaceAddressLinkDescriptorsSubTLV ipv4InterfaceAddressTLV = new IPv4InterfaceAddressLinkDescriptorsSubTLV(); + IPv4NeighborAddressLinkDescriptorSubTLV ipv4NeighborAddressTLV = new IPv4NeighborAddressLinkDescriptorSubTLV(); + ipv4InterfaceAddressTLV.setIpv4Address(addressList.get(0)); + ipv4NeighborAddressTLV.setIpv4Address(addressList.get(1)); + linkNLRI.setIpv4InterfaceAddressTLV(ipv4InterfaceAddressTLV); + linkNLRI.setIpv4NeighborAddressTLV(ipv4NeighborAddressTLV); + + //2.2.2. Link Local/Remote identifiers TLV + if (localRemoteIfList != null){ + LinkLocalRemoteIdentifiersLinkDescriptorSubTLV linkIdentifiersTLV = new LinkLocalRemoteIdentifiersLinkDescriptorSubTLV(); + linkIdentifiersTLV.setLinkLocalIdentifier(localRemoteIfList.get(0)); + linkIdentifiersTLV.setLinkRemoteIdentifier(localRemoteIfList.get(1)); + linkNLRI.setLinkIdentifiersTLV(linkIdentifiersTLV); + } + + //2.2.3 LinkDelay + if (te_info != null){ + if(te_info.getUndirLinkDelay() != null){ + int undirLinkDelay = te_info.getUndirLinkDelay().getDelay(); + UndirectionalLinkDelayDescriptorSubTLV uSTLV =new UndirectionalLinkDelayDescriptorSubTLV(); + uSTLV.setDelay(undirLinkDelay); + linkNLRI.setUndirectionalLinkDelayTLV(uSTLV); + } + if(te_info.getUndirDelayVar() != null){ + int undirDelayVar = te_info.getUndirDelayVar().getDelayVar(); + UndirectionalDelayVariationDescriptorSubTLV uSTLV =new UndirectionalDelayVariationDescriptorSubTLV(); + uSTLV.setDelayVar(undirDelayVar); + linkNLRI.setUndirectionalDelayVariationTLV(uSTLV); + } + if(te_info.getMinMaxUndirLinkDelay() != null){ + int minDelay = te_info.getMinMaxUndirLinkDelay().getLowDelay(); + int maxDelay = te_info.getMinMaxUndirLinkDelay().getHighDelay(); + MinMaxUndirectionalLinkDelayDescriptorSubTLV uSTLV =new MinMaxUndirectionalLinkDelayDescriptorSubTLV(); + uSTLV.setHighDelay(maxDelay); + uSTLV.setLowDelay(minDelay); + linkNLRI.setMinMaxUndirectionalLinkDelayTLV(uSTLV); + } + if(te_info.getUndirLinkLoss() != null){ + int linkLoss = te_info.getUndirLinkLoss().getLinkLoss(); + UndirectionalLinkLossDescriptorSubTLV uSTLV =new UndirectionalLinkLossDescriptorSubTLV(); + uSTLV.setLinkLoss(linkLoss); + linkNLRI.setUndirectionalLinkLossTLV(uSTLV); + } + if(te_info.getUndirResidualBw() != null){ + int resBw = te_info.getUndirResidualBw().getResidualBw(); + UndirectionalResidualBandwidthDescriptorSubTLV uSTLV =new UndirectionalResidualBandwidthDescriptorSubTLV(); + uSTLV.setResidualBw(resBw); + linkNLRI.setUndirectionalResidualBwTLV(uSTLV); + } + if(te_info.getUndirAvailableBw() != null){ + int availableBw = te_info.getUndirAvailableBw().getAvailableBw(); + UndirectionalAvailableBandwidthDescriptorSubTLV uSTLV =new UndirectionalAvailableBandwidthDescriptorSubTLV(); + uSTLV.setAvailableBw(availableBw); + linkNLRI.setUndirectionalAvailableBwTLV(uSTLV); + } + if(te_info.getUndirUtilizedBw() != null){ + int utilizedBw = te_info.getUndirUtilizedBw().getUtilizedBw(); + UndirectionalUtilizedBandwidthDescriptorSubTLV uSTLV =new UndirectionalUtilizedBandwidthDescriptorSubTLV(); + uSTLV.setUtilizedBw(utilizedBw); + linkNLRI.setUndirectionalUtilizedBwTLV(uSTLV); + } + + } + linkNLRI.setIdentifier(this.identifier); + BGP_LS_MP_Reach_Attribute ra= new BGP_LS_MP_Reach_Attribute(); + ra.setLsNLRI(linkNLRI); + + pathAttributes.add(ra); + return update; + } + /** + * Funcion que crea un mensaje OSPF inventado desde cero. + * Solo se meten en el mensaje los campos: + * - source + * - destino + * - maximun bandwithd + * @return OSPFv2 Link State Update Packet + */ + public static OSPFv2LinkStateUpdatePacket createMsgOSPF(){ + Inet4Address src = null; + Inet4Address dst = null; + MaximumBandwidth maximumBandwidth = new MaximumBandwidth(); + maximumBandwidth.setMaximumBandwidth(100); + UnreservedBandwidth unreservedBandwidth = new UnreservedBandwidth(); + float[] unReservedB = new float[8]; + unReservedB[0]=18309; + unReservedB[1]=130; + unreservedBandwidth.setUnreservedBandwidth(unReservedB); + try { + src = (Inet4Address) Inet4Address.getByName( "179.123.123.123"); + dst = (Inet4Address) Inet4Address.getByName( "179.123.123.111"); + } catch (UnknownHostException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + OSPFv2LinkStateUpdatePacket ospfv2Packet = new OSPFv2LinkStateUpdatePacket(); + ospfv2Packet.setRouterID(src); + LinkedList lsaList = new LinkedList(); + OSPFTEv2LSA lsa = new OSPFTEv2LSA(); + LinkTLV linkTLV=new LinkTLV(); + lsa.setLinkTLV(linkTLV); + + linkTLV.setMaximumBandwidth(maximumBandwidth); + linkTLV.setUnreservedBandwidth(unreservedBandwidth); + LocalInterfaceIPAddress localInterfaceIPAddress= new LocalInterfaceIPAddress(); + LinkedList lista =localInterfaceIPAddress.getLocalInterfaceIPAddressList(); + lista.add(src); + linkTLV.setLocalInterfaceIPAddress(localInterfaceIPAddress); + RemoteInterfaceIPAddress remoteInterfaceIPAddress= new RemoteInterfaceIPAddress(); + LinkedList listar = remoteInterfaceIPAddress.getRemoteInterfaceIPAddressList(); + listar.add(dst); + linkTLV.setRemoteInterfaceIPAddress(remoteInterfaceIPAddress); + LinkID linkID = new LinkID(); + linkID.setLinkID(dst); + linkTLV.setLinkID(linkID); + // if (edge.getTE_info().getAvailableLabels() != null){ + // linkTLV.setAvailableLabels(edge.getTE_info().getAvailableLabels()); + // } + lsaList.add(lsa); + + ospfv2Packet.setLSAlist(lsaList); + return ospfv2Packet; + } + + //* Funcion que decodifica un mensaje OSPFv2LinkStateUpdatePacket creando con los campos extraidos un mensaje BGP4 update. + public BGP4Update decodificarMsgOSPF(OSPFv2LinkStateUpdatePacket ospfv2Packet){ + boolean intradomain = true; + Inet4Address localIPAddress = ospfv2Packet.getRouterID(); + Inet4Address remoteIPAddress = null; + long localInterfaceIPAddress = -1; + long remoteInterfaceIPAddress = -1; + Inet4Address remoteASNumber = null; + LinkedList lsaList; + OSPFTEv2LSA lsa; + //GMPLS Parameter + AvailableLabels al = null; + //MPLS Parameter + float maxBandwidth = 0; + float[] unBandwidth = null; + float maximumReservableBandwidth=0; + + lsaList = ((OSPFv2LinkStateUpdatePacket)ospfv2Packet).getLSAlist(); + for (int i =0;i< lsaList.size();i++){ + if (lsaList.get(i).getLStype() == LSATypes.TYPE_10_OPAQUE_LSA){ + lsa=(OSPFTEv2LSA)lsaList.get(i); + log.debug("Starting to process LSA"); + + LinkTLV linkTLV = lsa.getLinkTLV(); + if (linkTLV!=null){ + //Local and Remote interface IP address + remoteIPAddress = linkTLV.getLinkID().getLinkID(); + log.debug("Remote IP Address: "+remoteIPAddress); + localInterfaceIPAddress = linkTLV.getLinkLocalRemoteIdentifiers().getLinkLocalIdentifier(); + log.debug("Local Interface: "+localInterfaceIPAddress); + remoteInterfaceIPAddress =linkTLV.getLinkLocalRemoteIdentifiers().getLinkRemoteIdentifier(); + log.debug("Remote Interface: "+remoteInterfaceIPAddress); + + //MPLS fields + if (linkTLV.getMaximumBandwidth() != null) + maxBandwidth = linkTLV.getMaximumBandwidth().getMaximumBandwidth(); + if (linkTLV.getUnreservedBandwidth() != null) + unBandwidth = linkTLV.getUnreservedBandwidth().getUnreservedBandwidth(); + if (linkTLV.getMaximumReservableBandwidth()!= null) + maximumReservableBandwidth = linkTLV.getMaximumReservableBandwidth().getMaximumReservableBandwidth(); + + //GMPLS + al = linkTLV.getAvailableLabels(); + //FIXME: Como ver si es inter o intra domain + if (linkTLV.getRemoteASNumber() != null) + remoteASNumber = linkTLV.getRemoteASNumber().getRemoteASNumber(); + + } + } + + } + //Create the address list + ArrayList addressList = new ArrayList(); + addressList.add(localIPAddress); + addressList.add(remoteIPAddress); + //Create the interface list + ArrayList localRemoteIfList = new ArrayList(); + localRemoteIfList.add(localInterfaceIPAddress); + localRemoteIfList.add(remoteInterfaceIPAddress); + + + //Create the domain List + ArrayList domainList = new ArrayList(2); + //FIXME CHECK IF THIS METHOD IS USED + //return createMsgUpdateLinkNLRI(addressList,localRemoteIfList,23,maxBandwidth,unBandwidth,maximumReservableBandwidth,al, 0,0, domainList, intradomain, null); + return null; + } + + public boolean isSendTopology() { + return sendTopology; + } + + + public void setSendTopology(boolean sendTopology) { + this.sendTopology = sendTopology; + } + + public void setisTest(boolean test) { + this.isTest = test; + } + + public boolean getisTest() { + return this.isTest; + } + + + public BGP4SessionsInformation getBgp4SessionsInformation() { + return bgp4SessionsInformation; + } + + + public void setBgp4SessionsInformation( + BGP4SessionsInformation bgp4SessionsInformation) { + this.bgp4SessionsInformation = bgp4SessionsInformation; + } + + + public void setInstanceId(int instanceId) { + this.instanceId = instanceId; + } + + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/BGP4DomainTEDB.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/BGP4DomainTEDB.java new file mode 100644 index 000000000..512467ccf --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/BGP4DomainTEDB.java @@ -0,0 +1,51 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.tedb; + +import java.util.LinkedList; +import eu.teraflow.tid.tedb.InterDomainEdge; +import eu.teraflow.tid.tedb.TEDB; + +public class BGP4DomainTEDB implements TEDB { + + @Override + public void initializeFromFile(String file) { + // TODO Auto-generated method stub + + } + + @Override + public void initializeFromFile(String file, String learnFrom) { + + } + + @Override + public boolean isITtedb() { + // TODO Auto-generated method stub + return false; + } + + @Override + public String printTopology() { + // TODO Auto-generated method stub + return null; + } + + @Override + public LinkedList getInterDomainLinks() { + // TODO Auto-generated method stub + return null; + } +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/BGP4IntradomainTEDB.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/BGP4IntradomainTEDB.java new file mode 100644 index 000000000..0f027c693 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/BGP4IntradomainTEDB.java @@ -0,0 +1,67 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.tedb; + +import java.net.Inet4Address; +import java.util.Hashtable; +import java.util.LinkedList; + +import eu.teraflow.tid.tedb.InterDomainEdge; + +public class BGP4IntradomainTEDB implements IntraTEDBS { + + Hashtable tedb; + @Override + public void initializeFromFile(String file) { + // TODO Auto-generated method stub + + } + + @Override + public void initializeFromFile(String file, String learnFrom) { + + } + + @Override + public boolean isITtedb() { + // TODO Auto-generated method stub + return false; + } + + @Override + public String printTopology() { + // TODO Auto-generated method stub + return null; + } + + @Override + public LinkedList getInterDomainLinks() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void addIntradomainEdge() { + // TODO Auto-generated method stub + + } + + @Override + public void addIntradomainNode(Inet4Address domain, Inet4Address node) { + BGP4DomainTEDB bgp4TEDB = tedb.get(domain); + + } + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/IntraTEDBS.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/IntraTEDBS.java new file mode 100644 index 000000000..ae4946dd2 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/tedb/IntraTEDBS.java @@ -0,0 +1,29 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.tedb; + +import java.net.Inet4Address; +import eu.teraflow.tid.tedb.TEDB; + +public interface IntraTEDBS extends TEDB { + + + //Metodo (annadir enlace intradominio) que le pases un domain id, + cosas que necesites para el intradomain edge. + //Las clases que implemente para esta interface ya tengra que ver c�mo hacerlo. Tener una hashtable. + public void addIntradomainEdge(); + public void addIntradomainNode(Inet4Address domain, Inet4Address node); + + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateDispatcher.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateDispatcher.java new file mode 100644 index 000000000..e77612ea6 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateDispatcher.java @@ -0,0 +1,56 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.updateTEDB; + +import java.net.Inet4Address; +import java.util.Hashtable; +import java.util.concurrent.LinkedBlockingQueue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import es.tid.bgp.bgp4.messages.BGP4Update; +import eu.teraflow.tid.bgp4Peer.tedb.IntraTEDBS; +import eu.teraflow.tid.tedb.DomainTEDB; +import eu.teraflow.tid.tedb.MultiDomainTEDB; +import eu.teraflow.tid.tedb.SimpleTEDB; +import eu.teraflow.tid.tedb.TEDB; + + +/** + * This class is in charge of storing the BGP4 update messages in a queue to be processing + * + * @author pac + * + */ +public class UpdateDispatcher { + + private Logger log; + private LinkedBlockingQueue updateList; + private UpdateProccesorThread upt; + + + public UpdateDispatcher(MultiDomainTEDB multiTedb,Hashtable intraTEDBs ){ + this.updateList=new LinkedBlockingQueue(); + this.upt=new UpdateProccesorThread(updateList, multiTedb,intraTEDBs ); + upt.start(); + log=LoggerFactory.getLogger("BGP4Server"); + } + public void dispatchRequests(BGP4Update updateMessage){ + updateList.add(updateMessage); + } + + + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateLink.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateLink.java new file mode 100644 index 000000000..df711c284 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdateLink.java @@ -0,0 +1,94 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.updateTEDB; + +import java.net.Inet4Address; +import java.util.ArrayList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import es.tid.bgp.bgp4.update.fields.LinkNLRI; +import es.tid.bgp.bgp4.update.tlv.linkstate_attribute_tlvs.MaxReservableBandwidthLinkAttribTLV; +import es.tid.bgp.bgp4.update.tlv.linkstate_attribute_tlvs.MaximumLinkBandwidthLinkAttribTLV; +import es.tid.bgp.bgp4.update.tlv.linkstate_attribute_tlvs.UnreservedBandwidthLinkAttribTLV; +import es.tid.bgp.bgp4.update.tlv.node_link_prefix_descriptor_subTLVs.AutonomousSystemNodeDescriptorSubTLV; +import es.tid.bgp.bgp4.update.tlv.node_link_prefix_descriptor_subTLVs.NodeDescriptorsSubTLV; +import es.tid.bgp.bgp4.update.tlv.node_link_prefix_descriptor_subTLVs.NodeDescriptorsSubTLVTypes; +import es.tid.ospf.ospfv2.lsa.LSA; +/** + * This class is used to control BGP updates (not changing database when is a 'refresh BGP message') + * + * WARNING: we only control when adding new link or when bitmap changes. + * @author baam + * + */ +public class UpdateLink { + + + private MaximumLinkBandwidthLinkAttribTLV maximumLinkBandwidthTLV; + private MaxReservableBandwidthLinkAttribTLV maxReservableBandwidthTLV; + private UnreservedBandwidthLinkAttribTLV unreservedBandwidthTLV; + private LinkNLRI linkNLRI; + private Inet4Address localDomainID; + private Inet4Address localRouterASBR; + private Inet4Address remoteDomainID; + private Inet4Address remoteRouterASBR; + private byte[] bitmap; + private byte[] bitmapReserved; + + public UpdateLink(Inet4Address remote, Inet4Address local, byte[] bitMap, byte[] bitmapRes) { + this.bitmap=new byte[bitMap.length]; + for(int i=0; i updateList; + + /** LINK ATTRIBUTE TLVs */ + MaximumLinkBandwidthLinkAttribTLV maximumLinkBandwidthTLV; + MaxReservableBandwidthLinkAttribTLV maxReservableBandwidthTLV; + UnreservedBandwidthLinkAttribTLV unreservedBandwidthTLV; + AdministrativeGroupLinkAttribTLV administrativeGroupTLV; + LinkProtectionTypeLinkAttribTLV linkProtectionTLV; + MetricLinkAttribTLV metricTLV; + IPv4RouterIDLocalNodeLinkAttribTLV iPv4RouterIDLocalNodeLATLV; + IPv4RouterIDRemoteNodeLinkAttribTLV iPv4RouterIDRemoteNodeLATLV; + DefaultTEMetricLinkAttribTLV TEMetricTLV; + TransceiverClassAndAppAttribTLV transceiverClassAndAppATLV; + MF_OTPAttribTLV mF_OTP_ATLV; + int linkDelay; + int linkDelayVar; + int minDelay; + int maxDelay; + int linkLoss; + int residualBw; + int availableBw; + int utilizedBw; + /** NODE ATTRIBUTE TLVs + * Ipv4 of local node link attribute TLV also used + * + * */ + NodeFlagBitsNodeAttribTLV nodeFlagBitsTLV = new NodeFlagBitsNodeAttribTLV(); + NodeNameNodeAttribTLV nodeNameTLV = new NodeNameNodeAttribTLV(); + IS_IS_AreaIdentifierNodeAttribTLV areaIDTLV = new IS_IS_AreaIdentifierNodeAttribTLV(); + SidLabelNodeAttribTLV sidTLV = new SidLabelNodeAttribTLV(); + + /**PREFIX ATTRIBUTE TLVs */ + IGPFlagBitsPrefixAttribTLV igpFlagBitsTLV = new IGPFlagBitsPrefixAttribTLV(); + RouteTagPrefixAttribTLV routeTagTLV = new RouteTagPrefixAttribTLV(); + PrefixMetricPrefixAttribTLV prefixMetricTLV = new PrefixMetricPrefixAttribTLV(); + OSPFForwardingAddressPrefixAttribTLV OSPFForwardingAddrTLV = new OSPFForwardingAddressPrefixAttribTLV(); + + private AvailableLabels availableLabels; + /** + * Logger + */ + private Logger log; + /** + * Topology database for interDomain Links which will be updated. + */ + private MultiDomainTEDB multiTedb; + /** + * Topology database for intradomain Links. It owns several domains and. + */ + private Hashtable intraTEDBs; + + private LinkedList updateLinks; + + private TE_Information te_info; + + + + + public UpdateProccesorThread(LinkedBlockingQueue updateList, + MultiDomainTEDB multiTedb ,Hashtable intraTEDBs ){ + log=LoggerFactory.getLogger("BGP4Server"); + running=true; + this.updateList=updateList; + this.multiTedb = multiTedb; + + this.intraTEDBs=intraTEDBs; + this.availableLabels= new AvailableLabels(); + this.updateLinks=new LinkedList(); + } + + /** + * Starts processing updates + */ + public void run(){ + + BGP4Update updateMsg; + UpdateMsgList updateMsgList = new UpdateMsgList();//write nodes and links info to a file + bgpMarshal m = new bgpMarshal();//add to json file + try { + m.bgpMarshaller(); + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + int j=0; //debug coverage + while (running && j<100) { + try { + clearAttributes(); + UpdateMsg update = new UpdateMsg();//class to send grpc message + PathAttribute att_ls = null; + PathAttribute att_mpreach = null; + PathAttribute att = null; + PathAttribute att_path = null; + updateMsg= updateList.take(); + + + log.info("Update Procesor Thread Reading the message: \n"+ updateMsg.toString()); + log.info("\n \n"); + //guille update processor + + + + log.debug("END string UPDATE msg"); + //Andrea To be checked + String learntFrom = updateMsg.getLearntFrom(); + log.info("Received from "+learntFrom); + ArrayList pathAttributeList = updateMsg.getPathAttributes(); + ArrayList pathAttributeListUtil = new ArrayList(); + update.setLearntFrom(learntFrom); + + + + // buscamos los dos atributos que nos interesan... + for (int i=0;i as_path_segments= ((AS_Path_Attribute)att_path).getAsPathSegments(); + AS_Path_Segment as_path_segment; + int as_path=0; + if(as_path_segments.size()>0){ + as_path_segment=as_path_segments.get(0); + int numberOfSeg=as_path_segment.getNumberOfSegments(); + as_path=as_path_segment.getSegments()[0]; + } + update.setAsPathSegment(as_path); + } + + if (pathAttributeListUtil != null){ + for (int i=0;i) ((BGP_LS_MP_Reach_Attribute)att).getLsNLRIList()){ + log.info("Link_NLRI"); + LinkNLRIMsg LnlriMsg = new LinkNLRIMsg((LinkNLRI)linkstateNLRI,learntFrom); + log.info("Link info: " + LnlriMsg.toString()); + updateMsgList.addLinkToJson(LnlriMsg); + update.addLink(LnlriMsg);//set for grpc msg + } + // } + continue; + case NLRITypes.Node_NLRI: + // NodeNLRIMsg NnlriMsg = new NodeNLRIMsg((NodeNLRI)nlri,learntFrom,currentName); + // log.info("Node_NLRI"); + // log.info("Node info: " + NnlriMsg.toString()); + // updateMsgList.addNodeToJson(NnlriMsg,currentName); + // update.setNode(NnlriMsg);//set for grpc msg + // currentName=null; + for(LinkStateNLRI linkstateNLRI : (List) ((BGP_LS_MP_Reach_Attribute)att).getLsNLRIList()){ + log.info("Node_NLRI"); + NodeNLRIMsg NnlriMsg = new NodeNLRIMsg((NodeNLRI)linkstateNLRI,learntFrom,currentName); + log.info("Node info: " + NnlriMsg.toString()); + updateMsgList.addNodeToJson(NnlriMsg,currentName); + update.addNode(NnlriMsg);//set for grpc msg + } + currentName=null; + continue; + case NLRITypes.Prefix_v4_NLRI://POR HACER... + log.info("Prefix_v4_NLRI"); + continue; + case NLRITypes.IT_Node_NLRI: + log.info("IT_Node_NLRI"); + continue; + default: + log.debug("Attribute Code unknown"); + } + + } + continue; + default: + log.debug("Attribute Code unknown"); + } + + + + }//fin for + try {m.writeFile(updateMsgList);} catch (IOException e) {e.printStackTrace();} + } + + // + + + log.warn("\n"); +// System.out.println(update.toString()); + //cambiar clase? + log.info("--->Sending to grpc manager"); + try { + grpcClient.sendGrpcUpdateMsg(update); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + //fin guille + + + + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + j++; + }//fin while + // try { + // channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); + // } catch (InterruptedException e) { + // // TODO Auto-generated catch block + // e.printStackTrace(); + // } + System.exit(0); + } + + + + /** + * Function which process the attribute link State. It updates the fields passed by argument. + */ + private void processAttributeLinkState(LinkStateAttribute lsAtt){ + + if (lsAtt.getMaximumLinkBandwidthTLV() != null){ + maximumLinkBandwidthTLV = lsAtt.getMaximumLinkBandwidthTLV(); + } + + if (lsAtt.getMaxReservableBandwidthTLV() != null){ + maxReservableBandwidthTLV = lsAtt.getMaxReservableBandwidthTLV(); + } + if (lsAtt.getUnreservedBandwidthTLV() != null){ + unreservedBandwidthTLV = lsAtt.getUnreservedBandwidthTLV(); + } + if(lsAtt.getAdministrativeGroupTLV() != null){ + administrativeGroupTLV = lsAtt.getAdministrativeGroupTLV(); + } + if(lsAtt.getLinkProtectionTLV() != null){ + linkProtectionTLV = lsAtt.getLinkProtectionTLV(); + } + if(lsAtt.getIPv4RouterIDLocalNodeLATLV()!= null){ + iPv4RouterIDLocalNodeLATLV = lsAtt.getIPv4RouterIDLocalNodeLATLV(); + } + if(lsAtt.getIPv4RouterIDRemoteNodeLATLV()!=null){ + iPv4RouterIDRemoteNodeLATLV = lsAtt.getIPv4RouterIDRemoteNodeLATLV(); + } + if(lsAtt.getMetricTLV() != null){ + metricTLV = lsAtt.getMetricTLV(); + } + if(lsAtt.getTEMetricTLV()!=null){ + TEMetricTLV = lsAtt.getTEMetricTLV(); + } + if(lsAtt.getNodeFlagBitsTLV()!= null){ + nodeFlagBitsTLV = lsAtt.getNodeFlagBitsTLV(); + } + if(lsAtt.getNodeNameTLV() != null){ + nodeNameTLV = lsAtt.getNodeNameTLV(); + } + if(lsAtt.getAreaIDTLV() != null){ + areaIDTLV = lsAtt.getAreaIDTLV(); + } + if(lsAtt.getIgpFlagBitsTLV() != null){ + igpFlagBitsTLV= lsAtt.getIgpFlagBitsTLV(); + } + if(lsAtt.getRouteTagTLV() != null){ + routeTagTLV = lsAtt.getRouteTagTLV(); + } + if(lsAtt.getOSPFForwardingAddrTLV() != null){ + OSPFForwardingAddrTLV = lsAtt.getOSPFForwardingAddrTLV(); + } + if(lsAtt.getSidLabelTLV()!=null){ + sidTLV = lsAtt.getSidLabelTLV(); + } + + if (lsAtt.getAvailableLabels() != null){ + this.availableLabels =lsAtt.getAvailableLabels(); + } + if (lsAtt.getMF_OTP_ATLV() != null){ + this.mF_OTP_ATLV =lsAtt.getMF_OTP_ATLV(); + } + + if (lsAtt.getTransceiverClassAndAppATLV() != null){ + this.transceiverClassAndAppATLV =lsAtt.getTransceiverClassAndAppATLV(); + } + + } + /** + * Function which process the link NLRI. It updates the fields passed by argument. + * @param linkNLRI + * @param maximumLinkBandwidthTLV + * @param maxReservableBandwidthTLV + * @param unreservedBandwidthTLV + * @param availableLabels + */ + + + /** Procesar un link significa: + * crear los vertices si no existen ya + * crear la edge si no existe ya + * crear la te_info o actualizarla + * @param linkNLRI + * @param learntFrom + */ + + + + private void clearAttributes(){ + maximumLinkBandwidthTLV= null; + maxReservableBandwidthTLV= null; + unreservedBandwidthTLV= null; + administrativeGroupTLV = null; + linkProtectionTLV =null; + metricTLV = null; + iPv4RouterIDLocalNodeLATLV = null; + iPv4RouterIDRemoteNodeLATLV = null; + TEMetricTLV = null; + transceiverClassAndAppATLV = null; + mF_OTP_ATLV = null; + availableLabels=null; + linkDelay=0; + linkDelayVar=0; + minDelay=0; + maxDelay=0; + linkLoss=0; + residualBw=0; + availableBw=0; + utilizedBw=0; + + } + + + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdaterThreadRedisTED.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdaterThreadRedisTED.java new file mode 100644 index 000000000..229fbe1de --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/bgp4Peer/updateTEDB/UpdaterThreadRedisTED.java @@ -0,0 +1,77 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.bgp4Peer.updateTEDB; + +import java.util.LinkedList; +import java.util.concurrent.LinkedBlockingQueue; + +import redis.clients.jedis.Jedis; +import es.tid.ospf.ospfv2.OSPFv2LinkStateUpdatePacket; +import es.tid.ospf.ospfv2.lsa.LSA; +import es.tid.ospf.ospfv2.lsa.LSATypes; +import es.tid.ospf.ospfv2.lsa.OSPFTEv2LSA; +import eu.teraflow.tid.tedb.DatabaseControlSimplifiedLSA; + +public class UpdaterThreadRedisTED extends Thread{ + //FIXME: Configure from file + private Jedis jedis; + private String host="localhost"; + + private int port=6379; + + private LinkedBlockingQueue redisOspfv2PacketQueue; + + public UpdaterThreadRedisTED(LinkedBlockingQueue redisOspfv2PacketQueue) { + // TODO Auto-generated constructor stub + + this.redisOspfv2PacketQueue = redisOspfv2PacketQueue; + jedis = new Jedis(host,port); + + + + } + + public void run() { + + LinkedList lsaList; + OSPFTEv2LSA lsa; + OSPFv2LinkStateUpdatePacket ospfv2Packet; + jedis.connect(); + //FIXE: Add disconnect + while(true){ + try { + + ospfv2Packet = redisOspfv2PacketQueue.take(); + lsaList = ((OSPFv2LinkStateUpdatePacket)ospfv2Packet).getLSAlist(); + for (int i =0;i< lsaList.size();i++){ + if (lsaList.get(i).getLStype() == LSATypes.TYPE_10_OPAQUE_LSA){ + lsa=(OSPFTEv2LSA)lsaList.get(i); + DatabaseControlSimplifiedLSA dcsl = new DatabaseControlSimplifiedLSA(); + dcsl.fillSimplifiedLsa(lsa); + String jsonLSA = dcsl.logJsonSimplifiedLSA(); + //RedisDatabaseHandler rdh = new RedisDatabaseHandler(); + String key="LSA:"+dcsl.getAdvertisingRouter().getHostAddress()+":"+dcsl.getLinkId().getHostAddress(); + String ret = jedis.set(key, jsonLSA); + jedis.sadd("TEDB",key); + } + } + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + +} \ No newline at end of file diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/DatabaseControlSimplifiedLSA.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/DatabaseControlSimplifiedLSA.java new file mode 100644 index 000000000..e56e45cf5 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/DatabaseControlSimplifiedLSA.java @@ -0,0 +1,174 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb; + +import java.net.Inet4Address; + +import com.google.gson.Gson; + +import es.tid.ospf.ospfv2.lsa.OSPFTEv2LSA; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.AvailableLabels; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.complexFields.BitmapLabelSet; + +/** + * + * Class for simplified database write of LSAs + * + * @author Fernando Mu�oz del Nuevo + * + * + * + */ + +public class DatabaseControlSimplifiedLSA { + + public Inet4Address advertisingRouter; + + public Inet4Address linkId; + + public long linkLocalIdentifier; + + public long linkRemoteIdentifier; + + public String bitmapLabelSet; + + public float maximumBandwidth; + + public float unreservedBandwidth; + + public float maximumReservableBandwidth; + + //protected LinkedList labelSet; + + public Inet4Address getAdvertisingRouter() { + return advertisingRouter; + } + + public void setAdvertisingRouter(Inet4Address advertisingRouter) { + this.advertisingRouter = advertisingRouter; + } + + public Inet4Address getLinkId() { + return linkId; + } + + public void setLinkId(Inet4Address linkId) { + this.linkId = linkId; + } + + public long getLinkLocalIdentifier() { + return linkLocalIdentifier; + } + + public void setLinkLocalIdentifier(long linkLocalIdentifier) { + this.linkLocalIdentifier = linkLocalIdentifier; + } + + public long getLinkRemoteIdentifier() { + return linkRemoteIdentifier; + } + + public void setLinkRemoteIdentifier(long linkRemoteIdentifier) { + this.linkRemoteIdentifier = linkRemoteIdentifier; + } + + public String getBitmapLabelSet() { + return bitmapLabelSet; + } + + public void setBitmapLabelSet(String bitmapLabelSet) { + this.bitmapLabelSet = bitmapLabelSet; + } + + public float getMaximumBandwidth() { + return maximumBandwidth; + } + + public void setMaximumBandwidth(float maximumBandwidth) { + this.maximumBandwidth = maximumBandwidth; + } + + public float getUnreservedBandwidth() { + return unreservedBandwidth; + } + + public void setUnreservedBandwidth(float unreservedBandwidth) { + this.unreservedBandwidth = unreservedBandwidth; + } + + public float getMaximumReservableBandwidth() { + return maximumReservableBandwidth; + } + + public void setMaximumReservableBandwidth(float maximumReservableBandwidth) { + this.maximumReservableBandwidth = maximumReservableBandwidth; + } + + public void fillBitmap(AvailableLabels availableLabels){ + + int num_wavelength = 0; + + + bitmapLabelSet = ""; + + while(num_wavelength < availableLabels.getLabelSet().getNumLabels()){ + + int num_byte=num_wavelength/8; + boolean isFree = ((((BitmapLabelSet)availableLabels.getLabelSet()).getBytesBitMap()[num_byte]&(0x80>>>(num_wavelength%8)))==0); + + if(isFree){ + bitmapLabelSet = bitmapLabelSet + "0"; + }else{ + bitmapLabelSet = bitmapLabelSet + "1"; + } + + num_wavelength++; + } + } + + public void fillSimplifiedLsa(OSPFTEv2LSA lsa){ + if (lsa.getAdvertisingRouter()!=null) + this.setAdvertisingRouter(lsa.getAdvertisingRouter()); + if (lsa.getLinkTLV().getLinkID().getLinkID()!=null) + this.setLinkId(lsa.getLinkTLV().getLinkID().getLinkID()); + if (lsa.getLinkTLV().getLinkLocalRemoteIdentifiers()!=null){ + this.setLinkLocalIdentifier(lsa.getLinkTLV().getLinkLocalRemoteIdentifiers().getLinkLocalIdentifier()); + this.setLinkRemoteIdentifier(lsa.getLinkTLV().getLinkLocalRemoteIdentifiers().getLinkRemoteIdentifier()); + } + if (lsa.getLinkTLV().getMaximumBandwidth()!=null) + this.setMaximumBandwidth(lsa.getLinkTLV().getMaximumBandwidth().getMaximumBandwidth()); + if (lsa.getLinkTLV().getUnreservedBandwidth()!=null){ + this.setMaximumBandwidth(lsa.getLinkTLV().getUnreservedBandwidth().unreservedBandwidth[0]); + } if (lsa.getLinkTLV().getMaximumReservableBandwidth()!=null){ + this.setMaximumReservableBandwidth(lsa.getLinkTLV().getMaximumReservableBandwidth().maximumReservableBandwidth); + } + + if (lsa.getLinkTLV().getAvailableLabels()!=null){ + this.fillBitmap(lsa.getLinkTLV().getAvailableLabels()); + } + } + + + public String logJsonSimplifiedLSA(){ + + Gson gson = new Gson(); + String json = gson.toJson(this); + + + return json; + + //IPInterfaceTrafficRequest iitr2 = gson.fromJson(json, DatabaseControlSimplifiedLSA.class); + } +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/DomainTEDB.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/DomainTEDB.java new file mode 100644 index 000000000..85ecd8fd3 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/DomainTEDB.java @@ -0,0 +1,85 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb; + +import java.net.Inet4Address; +import java.util.Hashtable; +import java.util.LinkedList; +import java.util.Set; + +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.complexFields.BitmapLabelSet; + + +public interface DomainTEDB extends TEDB { + + public Inet4Address getDomainID(); + + + public boolean belongsToDomain(Object addr); + + //public Object getDomainId(); + public ReachabilityEntry getReachabilityEntry(); + + //public byte[] getDomainReachabilityIPv4Prefix(); + + public LinkedList getInterDomainLinks(); + public Set getIntraDomainLinks(); + public String printInterDomainLinks(); + + public boolean containsVertex(Object vertex); + public WSONInformation getWSONinfo(); + public void setWSONinfo(WSONInformation wSONinfo); + public SSONInformation getSSONinfo(); + public void setSSONinfo(SSONInformation sSONinfo); + public void notifyWavelengthReservation(LinkedList sourceVertexList, LinkedList targetVertexList, int wavelength, boolean bidirectional); + public void notifyWavelengthReservationSSON (LinkedList sourceVertexList, LinkedList targetVertexList, int wavelength, boolean bidirectional, int m); + public void notifyWavelengthEndReservation(LinkedList sourceVertexList, LinkedList targetVertexList, int wavelength, boolean bidirectional); + public void notifyWavelengthChange(Object localInterfaceIPAddress,Object remoteInterfaceIPAddress,BitmapLabelSet previousBitmapLabelSet,BitmapLabelSet newBitmapLabelSet ); + public void notifyNewEdgeIP(Object source, Object destination, TE_Information informationTEDB); + public void register(TEDListener compAlgPreComp); + public void registerSSON(SSONListener compAlgPreComp); + + public void notifyNewVertex(Object vertex); + + public void notifyNewEdge (Object source, Object destination); + + public void clearAllReservations(); + + public void notifyWavelengthEndReservationSSON( + LinkedList sourceVertexList, + LinkedList targetVertexList, int wavelength, + boolean bidirectional, int m); + public void notifyWavelengthReservationWLAN( + LinkedList sourceVertexList, + LinkedList targetVertexList, LinkedList wlans, + boolean bidirectional); + + + public void createGraph(); + + + public Set getIntraDomainLinksvertexSet(); + + + public Hashtable getNodeTable(); + + public IT_Resources getItResources(); + public void setItResources(IT_Resources itResources); + + + + + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/EdgeUtils.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/EdgeUtils.java new file mode 100644 index 000000000..e2fafa238 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/EdgeUtils.java @@ -0,0 +1,34 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb; + +import java.net.Inet4Address; + +import es.tid.of.DataPathID; + +public class EdgeUtils { + + public static Object getEdge(String edge){ + Object router_id_addr; + try { //Router_type: IPv4 + router_id_addr = (Inet4Address) Inet4Address.getByName(edge); + } catch (Exception e) { //Router_type: DatapathID + router_id_addr = (DataPathID) DataPathID.getByName(edge); + //FIXME: See what to do if it is not IPv4 or DatapahID + } + return router_id_addr; + } + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/FileTEDBUpdater.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/FileTEDBUpdater.java new file mode 100644 index 000000000..ce5652267 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/FileTEDBUpdater.java @@ -0,0 +1,3585 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb; + +import es.tid.bgp.bgp4.update.tlv.linkstate_attribute_tlvs.DefaultTEMetricLinkAttribTLV; +import es.tid.bgp.bgp4.update.tlv.node_link_prefix_descriptor_subTLVs.*; +import es.tid.of.DataPathID; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.AvailableLabels; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.MaximumBandwidth; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.UnreservedBandwidth; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.complexFields.BitmapLabelSet; + +import es.tid.rsvp.constructs.gmpls.DWDMWavelengthLabel; +import es.tid.rsvp.objects.subobjects.IPv4prefixEROSubobject; +import org.jgrapht.graph.DirectedWeightedMultigraph; +import org.jgrapht.graph.SimpleDirectedWeightedGraph; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.*; +import org.w3c.dom.CharacterData; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.File; +import java.net.Inet4Address; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.LinkedList; + + +/** + * Convenience class to read Traffic Engineering Databases from XML files. + * + * @author ogondio + * + */ +public class FileTEDBUpdater { + + + /** + * Read a full network (no specific layer) + * @param fileName Name of the XML file + * @return Graph of the Network + */ + public static SimpleDirectedWeightedGraph readNetwork(String fileName){ + return FileTEDBUpdater.readNetwork(fileName,null,false,0,Integer.MAX_VALUE); + } + + /** + * Reads a specific layer from a Network XML file + * @param fileName Name of the XML file + * @param layer Layer + * @return Graph of the network + */ + public static SimpleDirectedWeightedGraph readNetwork(String fileName,String layer){ + return FileTEDBUpdater.readNetwork(fileName,layer,false,0,Integer.MAX_VALUE, false); + } + /** + * Reads a specific layer from a Network XML file + * It can treat all domains as a single domain + * @param fileName Name of the XML file + * @param layer Layer + * @param allDomains if all domains are read or not + * @return Graph of the network + */ + public static SimpleDirectedWeightedGraph readNetwork(String fileName,String layer,boolean allDomains){ + return FileTEDBUpdater.readNetwork(fileName,layer,allDomains,0,Integer.MAX_VALUE, false); + } + /** + * Reads a specific layer from a Network XML file + * It can treat all domains as a single domain + * @param fileName Name of the XML file + * @param layer Layer + * @param allDomains if all domains are read or not + * @param lambdaIni first lambda (n) + * @param lambdaEnd last lamnda (n) + * @return Graph of the network + */ + + public static SimpleDirectedWeightedGraph readNetwork(String fileName, String layer,boolean allDomains,int lambdaIni, int lambdaEnd) { + return FileTEDBUpdater.readNetwork(fileName,layer,allDomains,0,Integer.MAX_VALUE, false); + } + + + /** + * Reads a specific layer from a Network XML file. + * It can treat all domains as a single domain. + * + * @param fileName Name of the XML file + * @param layer Layer + * @param allDomains if all domains are read or not + * @param lambdaIni first lambda (n) + * @param lambdaEnd last lamnda (n) + * @param isSSONnetwork If the network supports Flexi Grid + * @return Graph of the network. + */ + public static SimpleDirectedWeightedGraph readNetwork(String fileName, String layer,boolean allDomains,int lambdaIni, int lambdaEnd, boolean isSSONnetwork) { + Logger log = LoggerFactory.getLogger("BGP4Peer"); + Object router_id_addr = null; + Object s_router_id_addr = null; + Object d_router_id_addr = null; + Object src_Numif_id = null; + Object dst_Numif_id = null; + + + //First, create the graph + SimpleDirectedWeightedGraph graph = new SimpleDirectedWeightedGraph(IntraDomainEdge.class); + + log.debug("1. SimpleDirectedWeightedGraph"); + + File file = new File(fileName); + try { + String domain_id = ""; + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document doc = builder.parse(file); + HashMapSIDS = new HashMap(); + HashMapSIDSDP = new HashMap(); + + NodeList nodes_domains = doc.getElementsByTagName("domain"); + if (layer!=null){ + log.debug("Reading topology, looking for layer "+ layer); + } + + + //First pass to get all the nodes + //If we need to read all the domains + for (int j = 0; j < nodes_domains.getLength(); j++) { + boolean readNetwork=false; + Element element1 = (Element) nodes_domains.item(j); + + if (layer!=null){ + NodeList domain_layer = element1.getElementsByTagName("layer"); + if (domain_layer.getLength()==1){ + Element layer_type = (Element) domain_layer.item(0); + log.debug("Layer: " + layer_type.getAttributeNode("type").getValue()); + log.debug("Reading network topology"); + if (layer_type.getAttributeNode("type").getValue().equals(layer)){ + readNetwork = true; + + } + if (layer.equals("interlayer")){ + readNetwork = true; + } + } + }else { + readNetwork=true; + } + if (readNetwork){ + Element element_domain = (Element) nodes_domains.item(j); + NodeList nodes_domain_id = element_domain.getElementsByTagName("domain_id"); + for (int k = 0; k < nodes_domain_id.getLength(); k++) { + Element domain_id_e = (Element) nodes_domain_id.item(0); + domain_id = getCharacterDataFromElement(domain_id_e); + log.debug("Loading nodes for domain: " + domain_id); + log.info("Loading topology from domain " + domain_id); + } + + NodeList nodes = element1.getElementsByTagName("node"); + for (int i = 0; i < nodes.getLength(); i++) { + Element element = (Element) nodes.item(i); + NodeList router_id_node = element.getElementsByTagName("router_id"); + Element router_id_e = (Element) router_id_node.item(0); + String router_id = getCharacterDataFromElement(router_id_e); + + log.info("Adding node " + router_id); + router_id_addr = EdgeUtils.getEdge(router_id); + graph.addVertex(router_id_addr); + + log.debug("About to look for SID"); + NodeList SID_aux = element.getElementsByTagName("sid"); + Element SID_e = (Element) SID_aux.item(0); + if (SID_e!=null) + { + log.debug("SID exist"); + int SID = Integer.parseInt(getCharacterDataFromElement(SID_e)); + + try { //Router_type: DatapathID + SIDS.put((Inet4Address) router_id_addr,SID); + log.debug("SID of node Inet4Address: "+SID); + } catch (Exception e) { //Router_type: DatapathID + SIDSDP.put((DataPathID)router_id_addr, SID); + log.debug("SID of node DataPathID: "+SID); + } + } + else + { + log.debug("SID not found"); + } + + } + } + } + + + //Next pass to get all the links + for (int j = 0; j < nodes_domains.getLength(); j++) { + + boolean readNetwork=false; + Element element1 = (Element) nodes_domains.item(j); + + if (layer!=null){ + NodeList domain_layer = element1.getElementsByTagName("layer"); + if (domain_layer.getLength()==1){ + Element layer_type = (Element) domain_layer.item(0); + log.debug("Layer: " + layer_type.getAttributeNode("type").getValue()); + log.debug("Reading Topology"); + if (layer_type.getAttributeNode("type").getValue().equals(layer)){ + readNetwork = true; + } + } + }else { + readNetwork=true; + } + log.debug("Read network = "+readNetwork); + if (readNetwork){ + Element element_domain = (Element) nodes_domains.item(j); + NodeList nodes_domain_id = element_domain.getElementsByTagName("domain_id"); + + for (int k = 0; k < nodes_domain_id.getLength(); k++) { + Element domain_id_e = (Element) nodes_domain_id.item(0); + domain_id = getCharacterDataFromElement(domain_id_e); + log.debug("Looking for links in domain: " + domain_id); + } + int numLabels=0; + + Boolean commonBitmapLabelSet = false; + NodeList edgeCommon = doc.getElementsByTagName("edgeCommon"); + int grid=0; + int cs=0; + int n=0; + for (int i = 0; i < edgeCommon.getLength(); i++) { + + Element edgeCommonElement = (Element) edgeCommon.item(i); + NodeList availableLabels_node = edgeCommonElement.getElementsByTagName("AvailableLabels"); + for (int k = 0; k < availableLabels_node.getLength(); k++) { + + Element availableLabels_e = (Element) availableLabels_node.item(k); + NodeList labelSetField_node = availableLabels_e.getElementsByTagName("LabelSetField"); + Element labelSetField_el = (Element) labelSetField_node.item(0); + if (labelSetField_el.getAttributeNode("type").getValue().equals("4")){//Tengo BitMapSet + //Crear un BitMapSet + + NodeList numbLabels_node = labelSetField_el.getElementsByTagName("numLabels"); + + Element numbLabels_e = (Element) numbLabels_node.item(0); + String numbLabels_s = getCharacterDataFromElement(numbLabels_e); + numLabels=Integer.parseInt(numbLabels_s); + + NodeList baseLabel_node = labelSetField_el.getElementsByTagName("baseLabel"); + Element baseLabel_e = (Element) baseLabel_node.item(0); + + float min_frequency; + + grid= Integer.parseInt(baseLabel_e.getAttributeNode("grid").getValue()); + + cs = Integer.parseInt(baseLabel_e.getAttributeNode("cs").getValue()); + boolean n_frequency_included=false; + if (baseLabel_e.getAttributeNode("n") != null ){ + n = Integer.parseInt(baseLabel_e.getAttributeNode("n").getValue()); + n_frequency_included = true; + } + else if (baseLabel_e.getAttributeNode("min_frequency") != null){ + String s_min_frequency = labelSetField_el.getAttributeNode("min_frequency").getValue(); + + min_frequency=Float.parseFloat(s_min_frequency); + n = ((int)min_frequency - 1471)/20; + n_frequency_included=true; + } + if (n_frequency_included){ + commonBitmapLabelSet = true; + }else{ + log.error("ERROR reading the xml file of the topology, you should enter "); + } + + } + } + + } + /*if(isSSONnetwork ==true){ + if(cs==4){ + numLabels=numLabels*4; + } + else if (cs==5){ + numLabels=numLabels*8; + } + }*/ + + NodeList edges = element_domain.getElementsByTagName("edge"); + for (int i = 0; i < edges.getLength(); i++) { + log.info("New Edge"); + Element element = (Element) edges.item(i); + //By default, all nodes are intradomain + String type; + Attr attr_type=element.getAttributeNode("type"); + if (attr_type==null){ + type="intradomain"; + }else { + type=attr_type.getValue(); + if (allDomains){ + if (type.equals("interdomain")){ + type="intradomain"; + } + } + + else if (type.equals("interlayer")){ + if (layer.equals("interlayer")){ + type="intradomain"; + } + + } + } + log.debug("type::"+type); + if (type.equals("intradomain")) { + IntraDomainEdge edge = new IntraDomainEdge(); + log.info("New Intradomain Edge"); + NodeList source = element.getElementsByTagName("source"); + Element source_router_el = (Element) source.item(0); + + NodeList source_router_id = source_router_el.getElementsByTagName("router_id"); + Element source_router_id_el = (Element) source_router_id.item(0); + String s_r_id = getCharacterDataFromElement(source_router_id_el); + s_router_id_addr= EdgeUtils.getEdge(s_r_id); + + NodeList source_if_id_nl = source_router_el.getElementsByTagName("if_id"); + Element source_if_id_el = (Element) source_if_id_nl.item(0); + String s_source_if_id; + int src_if_id = -1; + if (source_if_id_el!=null){ + s_source_if_id = getCharacterDataFromElement(source_if_id_el); + src_if_id = Integer.parseInt(s_source_if_id); + } + if (src_if_id!=-1) { + log.debug("SRC if id: "+src_if_id); + } + + NodeList source_Numif_id_nl = source_router_el.getElementsByTagName("NumIf_id"); + Element source_Numif_id_el = (Element) source_Numif_id_nl.item(0); + String s_source_Numif_id=null; + if (source_Numif_id_el!=null){ + s_source_Numif_id = getCharacterDataFromElement(source_Numif_id_el); + try { // src_Numif_id type : Inet4Address + src_Numif_id = (Inet4Address) Inet4Address.getByName(s_source_Numif_id); + } catch (Exception e) { // src_Numif_id type : DataPathID + src_Numif_id = DataPathID.getByName(s_source_Numif_id); + } + } + if (s_source_Numif_id!=null) { + log.debug("NumIf_id id: "+src_Numif_id); + } + + NodeList dest_nl = element.getElementsByTagName("destination"); + Element dest_el = (Element) dest_nl.item(0); + + NodeList dest_router_id_nl = dest_el.getElementsByTagName("router_id"); + Element dest_router_id_el = (Element) dest_router_id_nl.item(0); + String d_r_id = getCharacterDataFromElement(dest_router_id_el); + d_router_id_addr= EdgeUtils.getEdge(d_r_id); + + //Anyadimos los SID + if (SIDS.get(s_router_id_addr)!=null && SIDS.get(d_router_id_addr)!=null) + { + log.debug("setting SIDS src: "+SIDS.get(s_router_id_addr)+" dst: "+SIDS.get(d_router_id_addr)); + edge.setSrc_sid(SIDS.get(s_router_id_addr)); + edge.setDst_sid(SIDS.get(d_router_id_addr)); + log.debug("edge.getSrc_sid(): "+edge.getSrc_sid()); + log.debug("edge.getDst_sid(): "+edge.getDst_sid()); + } + else if (SIDSDP.get(s_router_id_addr)!=null && SIDSDP.get(d_router_id_addr)!=null) + { + log.debug("setting SIDSDP src: "+SIDSDP.get(s_router_id_addr)+" dst: "+SIDSDP.get(d_router_id_addr)); + edge.setSrc_sid(SIDSDP.get(s_router_id_addr)); + edge.setDst_sid(SIDSDP.get(d_router_id_addr)); + log.debug("edge.getSrc_sid(): "+edge.getSrc_sid()); + log.debug("edge.getDst_sid(): "+edge.getDst_sid()); + } + + + NodeList dest_if_id_nl = dest_el.getElementsByTagName("if_id"); + Element dest_if_id_el= (Element) dest_if_id_nl.item(0); + String s_dest_if_id; + int dst_if_id = -1; + if (dest_if_id_el!=null){ + s_dest_if_id = getCharacterDataFromElement(dest_if_id_el); + dst_if_id = Integer.parseInt(s_dest_if_id); + } + if (dst_if_id!=-1) { + log.debug("DST if id: "+dst_if_id); + } + + + NodeList dest_Numif_id_nl = dest_el.getElementsByTagName("NumIf_id"); + Element dest_Numif_id_el = (Element) dest_Numif_id_nl.item(0); + String s_dest_Numif_id=null; + + if (source_Numif_id_el!=null){ + s_dest_Numif_id = getCharacterDataFromElement(dest_Numif_id_el); + + try { // s_dest_Numif_id type : Inet4Address + dst_Numif_id = (Inet4Address) Inet4Address.getByName(s_dest_Numif_id); + } catch (Exception e) { // s_dest_Numif_id type : DataPathID + dst_Numif_id = DataPathID.getByName(s_dest_Numif_id); + } + } + if (s_dest_Numif_id!=null) { + log.debug("DST NumIf_id id: "+dst_Numif_id); + } + + // Añadimos interfaces Numeradas + if (src_Numif_id!=null){ + edge.setSrc_Numif_id(src_Numif_id); + }if (dst_Numif_id!=null){ + edge.setDst_Numif_id(dst_Numif_id); + }else{ + if (src_if_id != -1){ + edge.setSrc_if_id(src_if_id); + } + if (dst_if_id != -1){ + edge.setDst_if_id(dst_if_id); + } + } + + //DELAY, IF IT COMES.. + NodeList delay_ms_nl = element.getElementsByTagName("delay"); + if (delay_ms_nl.getLength()>0){ + + Element delay_ms_el = (Element)delay_ms_nl.item(0); + String s_delay_ms=getCharacterDataFromElement(delay_ms_el); + double delay_ms=Double.parseDouble(s_delay_ms); + edge.setDelay_ms(delay_ms); + } + + //TE Link information + NodeList maximum_bandwidth_nl = element.getElementsByTagName("maximum_bandwidth"); + if (maximum_bandwidth_nl!=null){ + if (maximum_bandwidth_nl.getLength()>0){ + if(edge.getTE_info()==null){ + TE_Information tE_info= new TE_Information(); + if (commonBitmapLabelSet){ + if(lambdaEnd!=Integer.MAX_VALUE){ + + tE_info.createBitmapLabelSet(numLabels, grid, cs, n,lambdaIni,lambdaEnd); + } + else + tE_info.createBitmapLabelSet(numLabels, grid, cs, n); + } + //tid.util.FuncionesUtiles.printByte(((BitmapLabelSet)tE_info.getAvailableLabels().getLabelSet()).getBytesBitmapReserved(),"getBytesBitmapReserved1:"); + edge.setTE_info(tE_info); + + } else { + TE_Information te_info = edge.getTE_info(); + if (commonBitmapLabelSet){ + // if(lambdaEnd!=Integer.MAX_VALUE){ + + // te_info.createBitmapLabelSet(numLabels, grid, cs, n,lambdaIni,lambdaEnd); + // } + // else + te_info.createBitmapLabelSet(numLabels, grid, cs, n); + } + //tid.util.FuncionesUtiles.printByte(((BitmapLabelSet)tE_info.getAvailableLabels().getLabelSet()).getBytesBitmapReserved(),"getBytesBitmapReserved1:"); + edge.setTE_info(te_info); + } + + Element maximum_bandwidth_el = (Element) maximum_bandwidth_nl.item(0); + String s_maximum_bandwidth = getCharacterDataFromElement(maximum_bandwidth_el); + + float maximum_bandwidth=Float.parseFloat(s_maximum_bandwidth); + MaximumBandwidth maximumBandwidth =new MaximumBandwidth(); + maximumBandwidth.setMaximumBandwidth(maximum_bandwidth); + (edge.getTE_info()).setMaximumBandwidth(maximumBandwidth); + + } + } + /** + * NodeList SID_aux = element.getElementsByTagName("sid"); + Element SID_e = (Element) SID_aux.item(0); + if (SID_e!=null) + { + log.info("SID existe"); + int SID = Integer.parseInt(getCharacterDataFromElement(SID_e)); + SIDS.put(router_id_addr,SID); + log.info("SID of node: "+SID); + } + else + { + log.info("SID not found"); + } + */ + + NodeList defaultmetric = element.getElementsByTagName("default_te_metric"); + Element metric_aux = (Element) defaultmetric.item(0); + + if (metric_aux != null){ + String s_metric_aux = getCharacterDataFromElement(metric_aux); + TE_Information tE_info; + int metric = Integer.parseInt(s_metric_aux); + DefaultTEMetricLinkAttribTLV defaultTeMetric= new DefaultTEMetricLinkAttribTLV(); + if(edge.getTE_info()==null){ + tE_info= new TE_Information(); + } + else{ + tE_info = edge.getTE_info(); + } + defaultTeMetric.setLinkMetric((long)metric); + tE_info.setDefaultTEMetric(defaultTeMetric); + edge.setTE_info(tE_info); + } + + NodeList unreserved_bandwidth_nl = element.getElementsByTagName("unreserved_bandwidth"); + if (unreserved_bandwidth_nl!=null){ + int num_u_b=unreserved_bandwidth_nl.getLength(); + UnreservedBandwidth unreservedBandwidth; + if (num_u_b>0){ + if(edge.getTE_info()==null){ + TE_Information tE_info= new TE_Information(); + if (commonBitmapLabelSet){ + if(lambdaEnd!=Integer.MAX_VALUE) + tE_info.createBitmapLabelSet(numLabels, grid, cs, n,lambdaIni,lambdaEnd); + else + tE_info.createBitmapLabelSet(numLabels, grid, cs, n); + } + edge.setTE_info(tE_info); + } + unreservedBandwidth =new UnreservedBandwidth(); + (edge.getTE_info()).setUnreservedBandwidth(unreservedBandwidth); + for(int k=0;k0){ + if(edge.getTE_info()==null){ + TE_Information tE_info= new TE_Information(); + + if (commonBitmapLabelSet){ + if(lambdaEnd!=Integer.MAX_VALUE){ + + tE_info.createBitmapLabelSet(numLabels, grid, cs, n,lambdaIni,lambdaEnd); + } + else + tE_info.createBitmapLabelSet(numLabels, grid, cs, n); + } + //tid.util.FuncionesUtiles.printByte(((BitmapLabelSet)tE_info.getAvailableLabels().getLabelSet()).getBytesBitmapReserved(),"getBytesBitmapReserved1:"); + edge.setTE_info(tE_info); + + } + + Element number_wlan_el = (Element) maximum_wlans_nl.item(0); + String s_number_wlans = getCharacterDataFromElement(number_wlan_el); + + int number_wlans=Integer.parseInt(s_number_wlans.replace("\n", "").replaceAll("\\s","")); + (edge.getTE_info()).setNumberWLANs(number_wlans); + (edge.getTE_info()).initWLANs(); + + } + } + + if(edge.getTE_info()==null){ + TE_Information tE_info= new TE_Information(); + edge.setTE_info(tE_info); + } + if (commonBitmapLabelSet){ + if(lambdaEnd!=Integer.MAX_VALUE) + edge.getTE_info().createBitmapLabelSet(numLabels, grid, cs, n,lambdaIni,lambdaEnd); + else + edge.getTE_info().createBitmapLabelSet(numLabels, grid, cs, n); + } + + NodeList availableLabels_node = element.getElementsByTagName("AvailableLabels"); + if ( availableLabels_node != null){ + for (int k = 0; k < availableLabels_node.getLength(); k++) { + Element availableLabels_e = (Element) availableLabels_node.item(k); + NodeList labelSetField_node = availableLabels_e.getElementsByTagName("LabelSetField"); + Element labelSetField_el = (Element) labelSetField_node.item(0); + if (labelSetField_el.getAttributeNode("type").getValue().equals("4")){//Tengo BitMapSet + + NodeList numbLabels_node = labelSetField_el.getElementsByTagName("numLabels"); + + Element numbLabels_e = (Element) numbLabels_node.item(0); + String numbLabels_s = getCharacterDataFromElement(numbLabels_e); + numLabels=Integer.parseInt(numbLabels_s); + + NodeList baseLabel_node = labelSetField_el.getElementsByTagName("baseLabel"); + Element baseLabel_e = (Element) baseLabel_node.item(0); + + byte[] bitmap=new byte[1]; + NodeList bitmap_node = labelSetField_el.getElementsByTagName("bitmap"); + int result=0; + Element bitmap_e = (Element) bitmap_node.item(0); + if (bitmap_e!=null){ + String bitmap_string=getCharacterDataFromElement(bitmap_e); + log.debug("Bitmap read: "+bitmap_string); + for (int p =0; p "); + } + } + } + + } + log.debug("Preparing to add edge"); + try{ + if(graph.containsEdge(s_router_id_addr, d_router_id_addr)){ + graph.getEdge(s_router_id_addr, d_router_id_addr).setNumberFibers(graph.getEdge(s_router_id_addr, d_router_id_addr).getNumberFibers()+1); + }else{ + log.debug("s_router_id_addr: "+s_router_id_addr.toString()+"; d_router_id_addr: "+d_router_id_addr.toString()+"; edge: "+edge); + graph.addEdge(s_router_id_addr, d_router_id_addr, edge); + graph.getEdge(s_router_id_addr, d_router_id_addr).setNumberFibers(1); + } + log.info("Adding edge from "+s_router_id_addr.toString()+" to "+d_router_id_addr.toString()+"; \n "+edge); + + }catch(Exception e){ + log.error("Problem with source "+s_router_id_addr+" destination "+d_router_id_addr); + e.printStackTrace(); + System.exit(-1); + } + } + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + log.debug("Info graph edge :: "+graph.edgeSet()); + return graph; + } + + /*private static SimpleDirectedWeightedGraph readGraphIntraDomain(Element element1, String layer, Logger log){ + + Object router_id_addr = null; + + HashMapSIDS = new HashMap(); + HashMapSIDSDP = new HashMap(); + + SimpleDirectedWeightedGraph graph = new SimpleDirectedWeightedGraph(IntraDomainEdge.class); + //NodeList nodes_domains = doc.getElementsByTagName("domain"); + boolean readNetwork=false; + //Element element1 = (Element) nodes_domains.item(j); + String domain_id = ""; + + if (layer!=null){ + NodeList domain_layer = element1.getElementsByTagName("layer"); + if (domain_layer.getLength()==1){ + Element layer_type = (Element) domain_layer.item(0); + log.info("Layer: " + layer_type.getAttributeNode("type").getValue()); + log.info("Reading network topology"); + if (layer_type.getAttributeNode("type").getValue().equals(layer)){ + readNetwork = true; + + } + if (layer.equals("interlayer")){ + readNetwork = true; + } + } + }else { + readNetwork=true; + } + if (readNetwork){ + Element element_domain = element1; + NodeList nodes_domain_id = element_domain.getElementsByTagName("domain_id"); + for (int k = 0; k < nodes_domain_id.getLength(); k++) { + Element domain_id_e = (Element) nodes_domain_id.item(0); + domain_id = getCharacterDataFromElement(domain_id_e); + //log.info("Looking for nodes in domain: " + domain_id); + } + + NodeList nodes = element1.getElementsByTagName("node"); + for (int i = 0; i < nodes.getLength(); i++) { + Element element = (Element) nodes.item(i); + NodeList router_id_node = element.getElementsByTagName("router_id"); + Element router_id_e = (Element) router_id_node.item(0); + String router_id = getCharacterDataFromElement(router_id_e); + + //log.info("Adding router_id " + router_id); + router_id_addr = EdgeUtils.getEdge(router_id); + graph.addVertex(router_id_addr); + + //log.info("About to look for SID"); + NodeList SID_aux = element.getElementsByTagName("sid"); + Element SID_e = (Element) SID_aux.item(0); + if (SID_e!=null) + { + //log.info("SID existe"); + int SID = Integer.parseInt(getCharacterDataFromElement(SID_e)); + + try { //Router_type: DatapathID + SIDS.put((Inet4Address) router_id_addr,SID); + //log.info("SID of node Inet4Address: "+SID); + } catch (Exception e) { //Router_type: DatapathID + SIDSDP.put((DataPathID)router_id_addr, SID); + //log.info("SID of node DataPathID: "+SID); + } + } + else + { + //log.info("SID not found"); + } + + } + } + return graph; + }*/ + + public static Hashtable readMultipleDomainSimpleNetworks(String fileName, String layer,boolean allDomains,int lambdaIni, int lambdaEnd, boolean isSSONnetwork) { + Logger log = LoggerFactory.getLogger("BGP4Peer"); + Object router_id_addr = null; + Object s_router_id_addr = null; + Object d_router_id_addr = null; + Object src_Numif_id = null; + Object dst_Numif_id = null; + + + Hashtable TEDBs = new Hashtable(); + + //First, create the graph + + log.debug("1. SimpleDirectedWeightedGraph"); + + File file = new File(fileName); + try { + String domain_id = ""; + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document doc = builder.parse(file); + HashMapSIDS = new HashMap(); + HashMapSIDSDP = new HashMap(); + + NodeList nodes_domains = doc.getElementsByTagName("domain"); + if (layer!=null){ + log.debug("Reading topology, looking for layer "+ layer); + } + + + //First pass to get all the nodes + //If we need to read all the domains + for (int j = 0; j < nodes_domains.getLength(); j++) { + boolean readNetwork=false; + Element element1 = (Element) nodes_domains.item(j); + SimpleTEDB tedb = new SimpleTEDB(); + SimpleDirectedWeightedGraph graph = new SimpleDirectedWeightedGraph(IntraDomainEdge.class); + + if (layer!=null){ + NodeList domain_layer = element1.getElementsByTagName("layer"); + if (domain_layer.getLength()==1){ + Element layer_type = (Element) domain_layer.item(0); + log.debug("Layer: " + layer_type.getAttributeNode("type").getValue()); + log.debug("Reading network topology"); + if (layer_type.getAttributeNode("type").getValue().equals(layer)){ + readNetwork = true; + + } + if (layer.equals("interlayer")){ + readNetwork = true; + } + } + }else { + readNetwork=true; + } + if (readNetwork){ + Element element_domain = (Element) nodes_domains.item(j); + NodeList nodes_domain_id = element_domain.getElementsByTagName("domain_id"); + for (int k = 0; k < nodes_domain_id.getLength(); k++) { + Element domain_id_e = (Element) nodes_domain_id.item(0); + domain_id = getCharacterDataFromElement(domain_id_e); + log.debug("Looking for nodes in domain: " + domain_id); + log.info("Loading topology from domain " + domain_id); + } + + NodeList itResourcesElement = element1.getElementsByTagName("it_resources"); + for (int i = 0; i < itResourcesElement.getLength(); i++) { + Element element = (Element) itResourcesElement.item(i); + + NodeList itResourcesControllerITList = element.getElementsByTagName("controller_it"); + Element itResourcesControllerITElement = (Element) itResourcesControllerITList.item(0); + String itResourcesControllerIT = getCharacterDataFromElement(itResourcesControllerITElement); + + NodeList itResourcesCpuList = element.getElementsByTagName("cpu"); + Element itResourcesCpuElement = (Element) itResourcesCpuList.item(0); + String itResourcesCpu = getCharacterDataFromElement(itResourcesCpuElement); + + NodeList itResourcesMemList = element.getElementsByTagName("mem"); + Element itResourcesMemElement = (Element) itResourcesMemList.item(0); + String itResourcesMem = getCharacterDataFromElement(itResourcesMemElement); + + NodeList itResourcesStorageList = element.getElementsByTagName("storage"); + Element itResourcesStorageElement = (Element) itResourcesStorageList.item(0); + String itResourcesStorage = getCharacterDataFromElement(itResourcesStorageElement); + + IT_Resources itResources = new IT_Resources(); + if (itResourcesControllerIT!=null) itResources.setControllerIT(itResourcesControllerIT); + if (itResourcesCpu!=null) itResources.setCpu(itResourcesCpu); + if (itResourcesMem!=null) itResources.setMem(itResourcesMem); + if (itResourcesStorage!=null) itResources.setStorage(itResourcesStorage); + + + tedb.setItResources(itResources); + + } + NodeList nodes = element1.getElementsByTagName("node"); + for (int i = 0; i < nodes.getLength(); i++) { + Element element = (Element) nodes.item(i); + NodeList router_id_node = element.getElementsByTagName("router_id"); + Element router_id_e = (Element) router_id_node.item(0); + String router_id = getCharacterDataFromElement(router_id_e); + + log.info("Adding node " + router_id); + router_id_addr = EdgeUtils.getEdge(router_id); + graph.addVertex(router_id_addr); + + log.debug("About to look for SID"); + NodeList SID_aux = element.getElementsByTagName("sid"); + Element SID_e = (Element) SID_aux.item(0); + if (SID_e!=null) + { + log.debug("SID exist"); + int SID = Integer.parseInt(getCharacterDataFromElement(SID_e)); + + try { //Router_type: DatapathID + SIDS.put((Inet4Address) router_id_addr,SID); + log.debug("SID of node Inet4Address: "+SID); + } catch (Exception e) { //Router_type: DatapathID + SIDSDP.put((DataPathID)router_id_addr, SID); + log.debug("SID of node DataPathID: "+SID); + } + } + else + { + log.debug("SID not found"); + } + + } + } + + tedb.setNetworkGraph(graph); + tedb.setDomainID((Inet4Address) Inet4Address.getByName(domain_id)); + TEDBs.put(domain_id,tedb); + } + + + //Next pass to get all the links + for (int j = 0; j < nodes_domains.getLength(); j++) { + SimpleDirectedWeightedGraph graph=null; + boolean readNetwork=false; + Element element1 = (Element) nodes_domains.item(j); + + if (layer!=null){ + NodeList domain_layer = element1.getElementsByTagName("layer"); + if (domain_layer.getLength()==1){ + Element layer_type = (Element) domain_layer.item(0); + log.debug("Layer: " + layer_type.getAttributeNode("type").getValue()); + log.debug("Reading Topology"); + if (layer_type.getAttributeNode("type").getValue().equals(layer)){ + readNetwork = true; + } + } + }else { + readNetwork=true; + } + log.debug("Read network = "+readNetwork); + if (readNetwork){ + Element element_domain = (Element) nodes_domains.item(j); + NodeList nodes_domain_id = element_domain.getElementsByTagName("domain_id"); + + for (int k = 0; k < nodes_domain_id.getLength(); k++) { + Element domain_id_e = (Element) nodes_domain_id.item(0); + domain_id = getCharacterDataFromElement(domain_id_e); + log.debug("Looking for links in domain: " + domain_id); + } + //System.out.println("VVV debug domain id:"+domain_id); + SimpleTEDB domainTEDB = (SimpleTEDB)TEDBs.get( domain_id); + graph = domainTEDB.getNetworkGraph(); + + int numLabels=0; + TE_Information tE_info_common=null; + Boolean commonBitmapLabelSet = false; + NodeList edgeCommon = element1.getElementsByTagName("edgeCommon"); + int grid=0; + int cs=0; + int n=0; + for (int i = 0; i < edgeCommon.getLength(); i++) { + Element edgeCommonElement = (Element) edgeCommon.item(i); + tE_info_common =readTE_INFOfromXml(tE_info_common,edgeCommonElement, false,numLabels, grid, cs, n, 0, Integer.MAX_VALUE); + NodeList availableLabels_node = edgeCommonElement.getElementsByTagName("AvailableLabels"); + for (int k = 0; k < availableLabels_node.getLength(); k++) { + Element availableLabels_e = (Element) availableLabels_node.item(k); + NodeList labelSetField_node = availableLabels_e.getElementsByTagName("LabelSetField"); + Element labelSetField_el = (Element) labelSetField_node.item(0); + if (labelSetField_el.getAttributeNode("type").getValue().equals("4")){//Tengo BitMapSet + //Crear un BitMapSet + + NodeList numbLabels_node = labelSetField_el.getElementsByTagName("numLabels"); + + Element numbLabels_e = (Element) numbLabels_node.item(0); + String numbLabels_s = getCharacterDataFromElement(numbLabels_e); + numLabels=Integer.parseInt(numbLabels_s); + + NodeList baseLabel_node = labelSetField_el.getElementsByTagName("baseLabel"); + Element baseLabel_e = (Element) baseLabel_node.item(0); + + float min_frequency; + + grid= Integer.parseInt(baseLabel_e.getAttributeNode("grid").getValue()); + + cs = Integer.parseInt(baseLabel_e.getAttributeNode("cs").getValue()); + boolean n_frequency_included=false; + if (baseLabel_e.getAttributeNode("n") != null ){ + n = Integer.parseInt(baseLabel_e.getAttributeNode("n").getValue()); + n_frequency_included = true; + } + else if (baseLabel_e.getAttributeNode("min_frequency") != null){ + String s_min_frequency = labelSetField_el.getAttributeNode("min_frequency").getValue(); + + min_frequency=Float.parseFloat(s_min_frequency); + n = ((int)min_frequency - 1471)/20; + n_frequency_included=true; + } + if (n_frequency_included){ + commonBitmapLabelSet = true; + }else{ + log.error("ERROR reading the xml file of the topology, you should enter "); + } + } + } + + } + /*if(isSSONnetwork ==true){ + if(cs==4){ + numLabels=numLabels*4; + } + else if (cs==5){ + numLabels=numLabels*8; + } + }*/ + + NodeList edges = element_domain.getElementsByTagName("edge"); + for (int i = 0; i < edges.getLength(); i++) { + log.debug("New Link"); + Element element = (Element) edges.item(i); + //By default, all nodes are intradomain + String type; + Attr attr_type=element.getAttributeNode("type"); + if (attr_type==null){ + type="intradomain"; + }else { + type=attr_type.getValue(); + /*if (allDomains){ + if (type.equals("interdomain")){ + type="intradomain"; + } + }*/ + //else if (type.equals("interlayer")){ + if (layer!=null && layer.equals("interlayer")){ + type="intradomain"; + } + + //} + } + log.debug("type::"+type); + if (type.equals("intradomain")) { + IntraDomainEdge edge = new IntraDomainEdge(); + NodeList source = element.getElementsByTagName("source"); + Element source_router_el = (Element) source.item(0); + + NodeList source_router_id = source_router_el.getElementsByTagName("router_id"); + Element source_router_id_el = (Element) source_router_id.item(0); + String s_r_id = getCharacterDataFromElement(source_router_id_el); + s_router_id_addr= EdgeUtils.getEdge(s_r_id); + + NodeList source_if_id_nl = source_router_el.getElementsByTagName("if_id"); + Element source_if_id_el = (Element) source_if_id_nl.item(0); + String s_source_if_id; + int src_if_id = -1; + if (source_if_id_el!=null){ + s_source_if_id = getCharacterDataFromElement(source_if_id_el); + src_if_id = Integer.parseInt(s_source_if_id); + } + log.debug("SRC if id: "+src_if_id); + + NodeList source_Numif_id_nl = source_router_el.getElementsByTagName("NumIf_id"); + Element source_Numif_id_el = (Element) source_Numif_id_nl.item(0); + String s_source_Numif_id; + if (source_Numif_id_el!=null){ + s_source_Numif_id = getCharacterDataFromElement(source_Numif_id_el); + try { // src_Numif_id type : Inet4Address + src_Numif_id = (Inet4Address) Inet4Address.getByName(s_source_Numif_id); + } catch (Exception e) { // src_Numif_id type : DataPathID + src_Numif_id = DataPathID.getByName(s_source_Numif_id); + } + } + + NodeList dest_nl = element.getElementsByTagName("destination"); + Element dest_el = (Element) dest_nl.item(0); + + NodeList dest_router_id_nl = dest_el.getElementsByTagName("router_id"); + Element dest_router_id_el = (Element) dest_router_id_nl.item(0); + String d_r_id = getCharacterDataFromElement(dest_router_id_el); + d_router_id_addr= EdgeUtils.getEdge(d_r_id); + + //Anyadimos los SID + if (SIDS.get(s_router_id_addr)!=null && SIDS.get(d_router_id_addr)!=null) + { + log.debug("setting SIDS src: "+SIDS.get(s_router_id_addr)+" dst: "+SIDS.get(d_router_id_addr)); + edge.setSrc_sid(SIDS.get(s_router_id_addr)); + edge.setDst_sid(SIDS.get(d_router_id_addr)); + log.debug("edge.getSrc_sid(): "+edge.getSrc_sid()); + log.debug("edge.getDst_sid(): "+edge.getDst_sid()); + } + else if (SIDSDP.get(s_router_id_addr)!=null && SIDSDP.get(d_router_id_addr)!=null) + { + log.debug("setting SIDSDP src: "+SIDSDP.get(s_router_id_addr)+" dst: "+SIDSDP.get(d_router_id_addr)); + edge.setSrc_sid(SIDSDP.get(s_router_id_addr)); + edge.setDst_sid(SIDSDP.get(d_router_id_addr)); + log.debug("edge.getSrc_sid(): "+edge.getSrc_sid()); + log.debug("edge.getDst_sid(): "+edge.getDst_sid()); + } + + + NodeList dest_if_id_nl = dest_el.getElementsByTagName("if_id"); + Element dest_if_id_el= (Element) dest_if_id_nl.item(0); + String s_dest_if_id; + int dst_if_id = -1; + if (dest_if_id_el!=null){ + s_dest_if_id = getCharacterDataFromElement(dest_if_id_el); + dst_if_id = Integer.parseInt(s_dest_if_id); + } + log.debug("DST if id: "+dst_if_id); + + NodeList dest_Numif_id_nl = dest_el.getElementsByTagName("NumIf_id"); + Element dest_Numif_id_el = (Element) dest_Numif_id_nl.item(0); + String s_dest_Numif_id; + + if (source_Numif_id_el!=null){ + s_dest_Numif_id = getCharacterDataFromElement(dest_Numif_id_el); + + try { // s_dest_Numif_id type : Inet4Address + dst_Numif_id = (Inet4Address) Inet4Address.getByName(s_dest_Numif_id); + } catch (Exception e) { // s_dest_Numif_id type : DataPathID + dst_Numif_id = DataPathID.getByName(s_dest_Numif_id); + } + } + // Añadimos interfaces Numeradas + if (src_Numif_id!=null){ + edge.setSrc_Numif_id(src_Numif_id); + }if (dst_Numif_id!=null){ + edge.setDst_Numif_id(dst_Numif_id); + }else{ + if (src_if_id != -1){ + edge.setSrc_if_id(src_if_id); + } + if (dst_if_id != -1){ + edge.setDst_if_id(dst_if_id); + } + } + + //DELAY, IF IT COMES.. + NodeList delay_ms_nl = element.getElementsByTagName("delay"); + if (delay_ms_nl.getLength()>0){ + + Element delay_ms_el = (Element)delay_ms_nl.item(0); + String s_delay_ms=getCharacterDataFromElement(delay_ms_el); + double delay_ms=Double.parseDouble(s_delay_ms); + edge.setDelay_ms(delay_ms); + } + + //TE Link information + edge.setTE_info(readTE_INFOfromXml(tE_info_common, element, commonBitmapLabelSet,numLabels, grid, cs, n,lambdaIni,lambdaEnd)); + + + NodeList availableLabels_node = element.getElementsByTagName("AvailableLabels"); + if ( availableLabels_node != null){ + for (int k = 0; k < availableLabels_node.getLength(); k++) { + Element availableLabels_e = (Element) availableLabels_node.item(k); + NodeList labelSetField_node = availableLabels_e.getElementsByTagName("LabelSetField"); + Element labelSetField_el = (Element) labelSetField_node.item(0); + if (labelSetField_el.getAttributeNode("type").getValue().equals("4")){//Tengo BitMapSet + + NodeList numbLabels_node = labelSetField_el.getElementsByTagName("numLabels"); + + Element numbLabels_e = (Element) numbLabels_node.item(0); + String numbLabels_s = getCharacterDataFromElement(numbLabels_e); + numLabels=Integer.parseInt(numbLabels_s); + + NodeList baseLabel_node = labelSetField_el.getElementsByTagName("baseLabel"); + Element baseLabel_e = (Element) baseLabel_node.item(0); + + byte[] bitmap=new byte[1]; + NodeList bitmap_node = labelSetField_el.getElementsByTagName("bitmap"); + int result=0; + Element bitmap_e = (Element) bitmap_node.item(0); + if (bitmap_e!=null){ + String bitmap_string=getCharacterDataFromElement(bitmap_e); + System.out.println("Bitmap read: "+bitmap_string); + for (int p =0; p "); + } + } + } + + } + log.debug("Preparing to add edge"); + log.debug("NODES IN GRAPH:: "+graph.vertexSet()); + try{ + if(graph.containsEdge(s_router_id_addr, d_router_id_addr)){ + log.debug("New Intradomain Edge"); + graph.getEdge(s_router_id_addr, d_router_id_addr).setNumberFibers(graph.getEdge(s_router_id_addr, d_router_id_addr).getNumberFibers()+1); + log.debug("s_router_id_addr: "+s_router_id_addr.toString()+"; d_router_id_addr: "+d_router_id_addr.toString()+"; edge: "+edge); + log.info("New intradomain link: "+s_router_id_addr.toString()+" --> "+d_router_id_addr.toString());//+" \n "+edge); + + }else{ + log.debug("s_router_id_addr: "+s_router_id_addr.toString()+"; d_router_id_addr: "+d_router_id_addr.toString()+"; edge: "+edge); + if(graph.containsVertex(d_router_id_addr)==false){ + //interDomain edge + //TODO + type="interdomain"; + + }else{ + graph.addEdge(s_router_id_addr, d_router_id_addr, edge); + graph.getEdge(s_router_id_addr, d_router_id_addr).setNumberFibers(1); + log.debug("New Intradomain Edge"); + log.info("New intradomain link: "+s_router_id_addr.toString()+" --> "+d_router_id_addr.toString());//+" \n "+edge); + + } + } + }catch(Exception e){ + log.error("Problem with source "+s_router_id_addr+" destination "+d_router_id_addr); + e.printStackTrace(); + System.exit(-1); + } + } + if(type.equals("interdomain")){ + log.debug("New Interdomain Edge"); + InterDomainEdge edge = new InterDomainEdge(); + TE_Information tE_info=readTE_INFOfromXml(tE_info_common,element, false,numLabels, grid, cs, n, 0, Integer.MAX_VALUE); + edge.setTE_info(tE_info); + NodeList source = element.getElementsByTagName("source"); + Element source_router_el = (Element) source.item(0); + NodeList source_router_id = source_router_el + .getElementsByTagName("router_id"); + Element source_router_id_el = (Element) source_router_id + .item(0); + String s_r_id = getCharacterDataFromElement(source_router_id_el); + log.debug("Edge Source router_id: " + s_r_id); + + try { // s_router_id_addr type: Inet4Address + s_router_id_addr = (Inet4Address) Inet4Address.getByName(s_r_id); + } catch (Exception e) {// s_router_id_addr type: DataPathID + s_router_id_addr = DataPathID.getByName(s_r_id); + } + Inet4Address source_domain_id = (Inet4Address) Inet4Address.getByName(domain_id); + log.debug("Edge Source domain_id: " + source_domain_id); + + NodeList source_if_id_nl = source_router_el + .getElementsByTagName("if_id"); + Element source_if_id_el = (Element) source_if_id_nl.item(0); + String s_source_if_id = getCharacterDataFromElement(source_if_id_el); + log.debug("Edge Source if_id: " + s_source_if_id); + int src_if_id = Integer.parseInt(s_source_if_id); + + NodeList dest_nl = element.getElementsByTagName("destination"); + Element dest_el = (Element) dest_nl.item(0); + NodeList dest_router_id_nl = dest_el + .getElementsByTagName("router_id"); + Element dest_router_id_el = (Element) dest_router_id_nl.item(0); + String d_r_id = getCharacterDataFromElement(dest_router_id_el); + log.debug("Edge Destination router_id: " + d_r_id); + try { // d_router_id_addr type: Inet4Address + d_router_id_addr = (Inet4Address) Inet4Address.getByName(d_r_id); + } catch (Exception e) { // d_router_id_addr type: DataPathID + d_router_id_addr = DataPathID.getByName(d_r_id); + } + //Inet4Address dest_domain_id = router_id_domain_ed.get(d_router_id_addr); + log.debug("Destination domain_id: "); + + NodeList dest_if_id_nl = dest_el.getElementsByTagName("if_id"); + Element dest_if_id_el = (Element) dest_if_id_nl.item(0); + String s_dest_if_id = getCharacterDataFromElement(dest_if_id_el); + log.debug("Edge Dest if_id: " + s_dest_if_id); + int dst_if_id = Integer.parseInt(s_dest_if_id); + + //router_id_domain_ed + //edge.setDomain_src_router(source_domain_id); + + edge.setSrc_if_id(src_if_id); + edge.setDst_if_id(dst_if_id); + edge.setDomain_src_router(source_domain_id); + //edge.setDomain_dst_router(dest_domain_id); + + edge.setSrc_router_id(s_router_id_addr); + edge.setDst_router_id(d_router_id_addr); + if(domainTEDB.getInterDomainLinks()==null){ + LinkedList interDomainLinks= new LinkedList(); + interDomainLinks.add(edge); + domainTEDB.setInterDomainLinks(interDomainLinks); + log.info("New interdomain link: "+s_router_id_addr.toString()+" --> "+d_router_id_addr.toString());//+"; \n "+edge); + + }else{ + domainTEDB.getInterDomainLinks().add(edge); + log.info("New interdomain link: "+s_router_id_addr.toString()+" --> "+d_router_id_addr.toString());//+"; \n "+edge); + + } + + } + } + + } + log.debug("Info graph edge :: "+graph.edgeSet()); + + } + } catch (Exception e) { + e.printStackTrace(); + } + + return TEDBs; + } + + public static Hashtable readMultipleDomainSimpleNetworks(String fileName, String layer,boolean allDomains,int lambdaIni, int lambdaEnd, boolean isSSONnetwork, String learntFrom) { + Logger log = LoggerFactory.getLogger("BGP4Peer"); + Object router_id_addr = null; + Object s_router_id_addr = null; + Object d_router_id_addr = null; + Object src_Numif_id = null; + Object dst_Numif_id = null; + + + Hashtable TEDBs = new Hashtable(); + + //First, create the graph + + log.debug("1. SimpleDirectedWeightedGraph"); + + File file = new File(fileName); + try { + String domain_id = ""; + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document doc = builder.parse(file); + HashMapSIDS = new HashMap(); + HashMapSIDSDP = new HashMap(); + + NodeList nodes_domains = doc.getElementsByTagName("domain"); + if (layer!=null){ + log.debug("Reading topology, looking for layer "+ layer); + } + + + //First pass to get all the nodes + //If we need to read all the domains + for (int j = 0; j < nodes_domains.getLength(); j++) { + boolean readNetwork=false; + Element element1 = (Element) nodes_domains.item(j); + SimpleTEDB tedb = new SimpleTEDB(); + SimpleDirectedWeightedGraph graph = new SimpleDirectedWeightedGraph(IntraDomainEdge.class); + + if (layer!=null){ + NodeList domain_layer = element1.getElementsByTagName("layer"); + if (domain_layer.getLength()==1){ + Element layer_type = (Element) domain_layer.item(0); + log.debug("Layer: " + layer_type.getAttributeNode("type").getValue()); + log.debug("Reading network topology"); + if (layer_type.getAttributeNode("type").getValue().equals(layer)){ + readNetwork = true; + + } + if (layer.equals("interlayer")){ + readNetwork = true; + } + } + }else { + readNetwork=true; + } + if (readNetwork){ + Element element_domain = (Element) nodes_domains.item(j); + NodeList nodes_domain_id = element_domain.getElementsByTagName("domain_id"); + for (int k = 0; k < nodes_domain_id.getLength(); k++) { + Element domain_id_e = (Element) nodes_domain_id.item(0); + domain_id = getCharacterDataFromElement(domain_id_e); + log.debug("Looking for nodes in domain: " + domain_id); + log.info("Loading topology from domain " + domain_id); + } + + NodeList itResourcesElement = element1.getElementsByTagName("it_resources"); + for (int i = 0; i < itResourcesElement.getLength(); i++) { + Element element = (Element) itResourcesElement.item(i); + + NodeList itResourcesControllerITList = element.getElementsByTagName("controller_it"); + Element itResourcesControllerITElement = (Element) itResourcesControllerITList.item(0); + String itResourcesControllerIT = getCharacterDataFromElement(itResourcesControllerITElement); + + NodeList itResourcesCpuList = element.getElementsByTagName("cpu"); + Element itResourcesCpuElement = (Element) itResourcesCpuList.item(0); + String itResourcesCpu = getCharacterDataFromElement(itResourcesCpuElement); + + NodeList itResourcesMemList = element.getElementsByTagName("mem"); + Element itResourcesMemElement = (Element) itResourcesMemList.item(0); + String itResourcesMem = getCharacterDataFromElement(itResourcesMemElement); + + NodeList itResourcesStorageList = element.getElementsByTagName("storage"); + Element itResourcesStorageElement = (Element) itResourcesStorageList.item(0); + String itResourcesStorage = getCharacterDataFromElement(itResourcesStorageElement); + + IT_Resources itResources = new IT_Resources(); + if (itResourcesControllerIT!=null){ + itResources.setControllerIT(itResourcesControllerIT); + itResources.setLearntFrom(learntFrom); + } + if (itResourcesCpu!=null) itResources.setCpu(itResourcesCpu); + if (itResourcesMem!=null) itResources.setMem(itResourcesMem); + if (itResourcesStorage!=null) { + itResources.setStorage(itResourcesStorage); + log.info("set learn from for it resources "+ itResources.toString()); + } + + tedb.setItResources(itResources); + + } + NodeList nodes = element1.getElementsByTagName("node"); + for (int i = 0; i < nodes.getLength(); i++) { + Element element = (Element) nodes.item(i); + NodeList router_id_node = element.getElementsByTagName("router_id"); + Element router_id_e = (Element) router_id_node.item(0); + String router_id = getCharacterDataFromElement(router_id_e); + + log.info("Adding node " + router_id); + router_id_addr = EdgeUtils.getEdge(router_id); + graph.addVertex(router_id_addr); + + log.debug("About to look for SID"); + NodeList SID_aux = element.getElementsByTagName("sid"); + Element SID_e = (Element) SID_aux.item(0); + if (SID_e!=null) + { + log.debug("SID exist"); + int SID = Integer.parseInt(getCharacterDataFromElement(SID_e)); + + try { //Router_type: DatapathID + SIDS.put((Inet4Address) router_id_addr,SID); + log.debug("SID of node Inet4Address: "+SID); + } catch (Exception e) { //Router_type: DatapathID + SIDSDP.put((DataPathID)router_id_addr, SID); + log.debug("SID of node DataPathID: "+SID); + } + } + else + { + log.debug("SID not found"); + } + + } + } + + tedb.setNetworkGraph(graph); + tedb.setDomainID((Inet4Address) Inet4Address.getByName(domain_id)); + TEDBs.put(domain_id,tedb); + } + + + //Next pass to get all the links + for (int j = 0; j < nodes_domains.getLength(); j++) { + SimpleDirectedWeightedGraph graph=null; + boolean readNetwork=false; + Element element1 = (Element) nodes_domains.item(j); + + if (layer!=null){ + NodeList domain_layer = element1.getElementsByTagName("layer"); + if (domain_layer.getLength()==1){ + Element layer_type = (Element) domain_layer.item(0); + log.debug("Layer: " + layer_type.getAttributeNode("type").getValue()); + log.debug("Reading Topology"); + if (layer_type.getAttributeNode("type").getValue().equals(layer)){ + readNetwork = true; + } + } + }else { + readNetwork=true; + } + log.debug("Read network = "+readNetwork); + if (readNetwork){ + Element element_domain = (Element) nodes_domains.item(j); + NodeList nodes_domain_id = element_domain.getElementsByTagName("domain_id"); + + for (int k = 0; k < nodes_domain_id.getLength(); k++) { + Element domain_id_e = (Element) nodes_domain_id.item(0); + domain_id = getCharacterDataFromElement(domain_id_e); + log.debug("Looking for links in domain: " + domain_id); + } + //System.out.println("VVV debug domain id:"+domain_id); + SimpleTEDB domainTEDB = (SimpleTEDB)TEDBs.get( domain_id); + graph = domainTEDB.getNetworkGraph(); + + int numLabels=0; + TE_Information tE_info_common=null; + Boolean commonBitmapLabelSet = false; + NodeList edgeCommon = element1.getElementsByTagName("edgeCommon"); + int grid=0; + int cs=0; + int n=0; + for (int i = 0; i < edgeCommon.getLength(); i++) { + Element edgeCommonElement = (Element) edgeCommon.item(i); + tE_info_common =readTE_INFOfromXml(tE_info_common,edgeCommonElement, false,numLabels, grid, cs, n, 0, Integer.MAX_VALUE); + NodeList availableLabels_node = edgeCommonElement.getElementsByTagName("AvailableLabels"); + for (int k = 0; k < availableLabels_node.getLength(); k++) { + Element availableLabels_e = (Element) availableLabels_node.item(k); + NodeList labelSetField_node = availableLabels_e.getElementsByTagName("LabelSetField"); + Element labelSetField_el = (Element) labelSetField_node.item(0); + if (labelSetField_el.getAttributeNode("type").getValue().equals("4")){//Tengo BitMapSet + //Crear un BitMapSet + + NodeList numbLabels_node = labelSetField_el.getElementsByTagName("numLabels"); + + Element numbLabels_e = (Element) numbLabels_node.item(0); + String numbLabels_s = getCharacterDataFromElement(numbLabels_e); + numLabels=Integer.parseInt(numbLabels_s); + + NodeList baseLabel_node = labelSetField_el.getElementsByTagName("baseLabel"); + Element baseLabel_e = (Element) baseLabel_node.item(0); + + float min_frequency; + + grid= Integer.parseInt(baseLabel_e.getAttributeNode("grid").getValue()); + + cs = Integer.parseInt(baseLabel_e.getAttributeNode("cs").getValue()); + boolean n_frequency_included=false; + if (baseLabel_e.getAttributeNode("n") != null ){ + n = Integer.parseInt(baseLabel_e.getAttributeNode("n").getValue()); + n_frequency_included = true; + } + else if (baseLabel_e.getAttributeNode("min_frequency") != null){ + String s_min_frequency = labelSetField_el.getAttributeNode("min_frequency").getValue(); + + min_frequency=Float.parseFloat(s_min_frequency); + n = ((int)min_frequency - 1471)/20; + n_frequency_included=true; + } + if (n_frequency_included){ + commonBitmapLabelSet = true; + }else{ + log.error("ERROR reading the xml file of the topology, you should enter "); + } + } + } + + } + /*if(isSSONnetwork ==true){ + if(cs==4){ + numLabels=numLabels*4; + } + else if (cs==5){ + numLabels=numLabels*8; + } + }*/ + + NodeList edges = element_domain.getElementsByTagName("edge"); + for (int i = 0; i < edges.getLength(); i++) { + log.debug("New Link"); + Element element = (Element) edges.item(i); + //By default, all nodes are intradomain + String type; + Attr attr_type=element.getAttributeNode("type"); + if (attr_type==null){ + type="intradomain"; + }else { + type=attr_type.getValue(); + /*if (allDomains){ + if (type.equals("interdomain")){ + type="intradomain"; + } + }*/ + //else if (type.equals("interlayer")){ + if (layer!=null && layer.equals("interlayer")){ + type="intradomain"; + } + + //} + } + log.debug("type::"+type); + if (type.equals("intradomain")) { + IntraDomainEdge edge = new IntraDomainEdge(); + NodeList source = element.getElementsByTagName("source"); + Element source_router_el = (Element) source.item(0); + edge.setLearntFrom(learntFrom); + NodeList source_router_id = source_router_el.getElementsByTagName("router_id"); + Element source_router_id_el = (Element) source_router_id.item(0); + String s_r_id = getCharacterDataFromElement(source_router_id_el); + s_router_id_addr= EdgeUtils.getEdge(s_r_id); + + NodeList source_if_id_nl = source_router_el.getElementsByTagName("if_id"); + Element source_if_id_el = (Element) source_if_id_nl.item(0); + String s_source_if_id; + int src_if_id = -1; + if (source_if_id_el!=null){ + s_source_if_id = getCharacterDataFromElement(source_if_id_el); + src_if_id = Integer.parseInt(s_source_if_id); + } + log.debug("SRC if id: "+src_if_id); + + NodeList source_Numif_id_nl = source_router_el.getElementsByTagName("NumIf_id"); + Element source_Numif_id_el = (Element) source_Numif_id_nl.item(0); + String s_source_Numif_id; + if (source_Numif_id_el!=null){ + s_source_Numif_id = getCharacterDataFromElement(source_Numif_id_el); + try { // src_Numif_id type : Inet4Address + src_Numif_id = (Inet4Address) Inet4Address.getByName(s_source_Numif_id); + } catch (Exception e) { // src_Numif_id type : DataPathID + src_Numif_id = DataPathID.getByName(s_source_Numif_id); + } + } + + NodeList dest_nl = element.getElementsByTagName("destination"); + Element dest_el = (Element) dest_nl.item(0); + + NodeList dest_router_id_nl = dest_el.getElementsByTagName("router_id"); + Element dest_router_id_el = (Element) dest_router_id_nl.item(0); + String d_r_id = getCharacterDataFromElement(dest_router_id_el); + d_router_id_addr= EdgeUtils.getEdge(d_r_id); + + //Anyadimos los SID + if (SIDS.get(s_router_id_addr)!=null && SIDS.get(d_router_id_addr)!=null) + { + log.debug("setting SIDS src: "+SIDS.get(s_router_id_addr)+" dst: "+SIDS.get(d_router_id_addr)); + edge.setSrc_sid(SIDS.get(s_router_id_addr)); + edge.setDst_sid(SIDS.get(d_router_id_addr)); + log.debug("edge.getSrc_sid(): "+edge.getSrc_sid()); + log.debug("edge.getDst_sid(): "+edge.getDst_sid()); + } + else if (SIDSDP.get(s_router_id_addr)!=null && SIDSDP.get(d_router_id_addr)!=null) + { + log.debug("setting SIDSDP src: "+SIDSDP.get(s_router_id_addr)+" dst: "+SIDSDP.get(d_router_id_addr)); + edge.setSrc_sid(SIDSDP.get(s_router_id_addr)); + edge.setDst_sid(SIDSDP.get(d_router_id_addr)); + log.debug("edge.getSrc_sid(): "+edge.getSrc_sid()); + log.debug("edge.getDst_sid(): "+edge.getDst_sid()); + } + + + NodeList dest_if_id_nl = dest_el.getElementsByTagName("if_id"); + Element dest_if_id_el= (Element) dest_if_id_nl.item(0); + String s_dest_if_id; + int dst_if_id = -1; + if (dest_if_id_el!=null){ + s_dest_if_id = getCharacterDataFromElement(dest_if_id_el); + dst_if_id = Integer.parseInt(s_dest_if_id); + } + log.debug("DST if id: "+dst_if_id); + + NodeList dest_Numif_id_nl = dest_el.getElementsByTagName("NumIf_id"); + Element dest_Numif_id_el = (Element) dest_Numif_id_nl.item(0); + String s_dest_Numif_id; + + if (source_Numif_id_el!=null){ + s_dest_Numif_id = getCharacterDataFromElement(dest_Numif_id_el); + + try { // s_dest_Numif_id type : Inet4Address + dst_Numif_id = (Inet4Address) Inet4Address.getByName(s_dest_Numif_id); + } catch (Exception e) { // s_dest_Numif_id type : DataPathID + dst_Numif_id = DataPathID.getByName(s_dest_Numif_id); + } + } + // Añadimos interfaces Numeradas + if (src_Numif_id!=null){ + edge.setSrc_Numif_id(src_Numif_id); + }if (dst_Numif_id!=null){ + edge.setDst_Numif_id(dst_Numif_id); + }else{ + if (src_if_id != -1){ + edge.setSrc_if_id(src_if_id); + } + if (dst_if_id != -1){ + edge.setDst_if_id(dst_if_id); + } + } + + //DELAY, IF IT COMES.. + NodeList delay_ms_nl = element.getElementsByTagName("delay"); + if (delay_ms_nl.getLength()>0){ + + Element delay_ms_el = (Element)delay_ms_nl.item(0); + String s_delay_ms=getCharacterDataFromElement(delay_ms_el); + double delay_ms=Double.parseDouble(s_delay_ms); + edge.setDelay_ms(delay_ms); + } + + //TE Link information + edge.setTE_info(readTE_INFOfromXml(tE_info_common, element, commonBitmapLabelSet,numLabels, grid, cs, n,lambdaIni,lambdaEnd)); + + + NodeList availableLabels_node = element.getElementsByTagName("AvailableLabels"); + if ( availableLabels_node != null){ + for (int k = 0; k < availableLabels_node.getLength(); k++) { + Element availableLabels_e = (Element) availableLabels_node.item(k); + NodeList labelSetField_node = availableLabels_e.getElementsByTagName("LabelSetField"); + Element labelSetField_el = (Element) labelSetField_node.item(0); + if (labelSetField_el.getAttributeNode("type").getValue().equals("4")){//Tengo BitMapSet + + NodeList numbLabels_node = labelSetField_el.getElementsByTagName("numLabels"); + + Element numbLabels_e = (Element) numbLabels_node.item(0); + String numbLabels_s = getCharacterDataFromElement(numbLabels_e); + numLabels=Integer.parseInt(numbLabels_s); + + NodeList baseLabel_node = labelSetField_el.getElementsByTagName("baseLabel"); + Element baseLabel_e = (Element) baseLabel_node.item(0); + + byte[] bitmap=new byte[1]; + NodeList bitmap_node = labelSetField_el.getElementsByTagName("bitmap"); + int result=0; + Element bitmap_e = (Element) bitmap_node.item(0); + if (bitmap_e!=null){ + String bitmap_string=getCharacterDataFromElement(bitmap_e); + System.out.println("Bitmap read: "+bitmap_string); + for (int p =0; p "); + } + } + } + + } + log.debug("Preparing to add edge"); + log.debug("NODES IN GRAPH:: "+graph.vertexSet()); + try{ + if(graph.containsEdge(s_router_id_addr, d_router_id_addr)){ + log.debug("New Intradomain Edge"); + graph.getEdge(s_router_id_addr, d_router_id_addr).setNumberFibers(graph.getEdge(s_router_id_addr, d_router_id_addr).getNumberFibers()+1); + log.debug("s_router_id_addr: "+s_router_id_addr.toString()+"; d_router_id_addr: "+d_router_id_addr.toString()+"; edge: "+edge); + log.info("New intradomain link: "+s_router_id_addr.toString()+" --> "+d_router_id_addr.toString());//+" \n "+edge); + + }else{ + log.debug("s_router_id_addr: "+s_router_id_addr.toString()+"; d_router_id_addr: "+d_router_id_addr.toString()+"; edge: "+edge); + if(graph.containsVertex(d_router_id_addr)==false){ + //interDomain edge + //TODO + type="interdomain"; + + }else{ + graph.addEdge(s_router_id_addr, d_router_id_addr, edge); + graph.getEdge(s_router_id_addr, d_router_id_addr).setNumberFibers(1); + log.debug("New Intradomain Edge"); + log.info("New intradomain link: "+s_router_id_addr.toString()+" --> "+d_router_id_addr.toString()+" learnt "+edge.getLearntFrom());//+" \n "+edge); + + } + } + }catch(Exception e){ + log.error("Problem with source "+s_router_id_addr+" destination "+d_router_id_addr); + e.printStackTrace(); + System.exit(-1); + } + } + if(type.equals("interdomain")){ + log.debug("New Interdomain Edge"); + InterDomainEdge edge = new InterDomainEdge(); + TE_Information tE_info=readTE_INFOfromXml(tE_info_common,element, false,numLabels, grid, cs, n, 0, Integer.MAX_VALUE); + edge.setTE_info(tE_info); + edge.setLearntFrom(learntFrom); + NodeList source = element.getElementsByTagName("source"); + Element source_router_el = (Element) source.item(0); + NodeList source_router_id = source_router_el + .getElementsByTagName("router_id"); + Element source_router_id_el = (Element) source_router_id + .item(0); + String s_r_id = getCharacterDataFromElement(source_router_id_el); + log.debug("Edge Source router_id: " + s_r_id); + + try { // s_router_id_addr type: Inet4Address + s_router_id_addr = (Inet4Address) Inet4Address.getByName(s_r_id); + } catch (Exception e) {// s_router_id_addr type: DataPathID + s_router_id_addr = DataPathID.getByName(s_r_id); + } + Inet4Address source_domain_id = (Inet4Address) Inet4Address.getByName(domain_id); + log.debug("Edge Source domain_id: " + source_domain_id); + + NodeList source_if_id_nl = source_router_el + .getElementsByTagName("if_id"); + Element source_if_id_el = (Element) source_if_id_nl.item(0); + String s_source_if_id = getCharacterDataFromElement(source_if_id_el); + log.debug("Edge Source if_id: " + s_source_if_id); + int src_if_id = Integer.parseInt(s_source_if_id); + + NodeList dest_nl = element.getElementsByTagName("destination"); + Element dest_el = (Element) dest_nl.item(0); + NodeList dest_router_id_nl = dest_el + .getElementsByTagName("router_id"); + Element dest_router_id_el = (Element) dest_router_id_nl.item(0); + String d_r_id = getCharacterDataFromElement(dest_router_id_el); + log.debug("Edge Destination router_id: " + d_r_id); + try { // d_router_id_addr type: Inet4Address + d_router_id_addr = (Inet4Address) Inet4Address.getByName(d_r_id); + } catch (Exception e) { // d_router_id_addr type: DataPathID + d_router_id_addr = DataPathID.getByName(d_r_id); + } + //Inet4Address dest_domain_id = router_id_domain_ed.get(d_router_id_addr); + log.debug("Destination domain_id: "); + + NodeList dest_if_id_nl = dest_el.getElementsByTagName("if_id"); + Element dest_if_id_el = (Element) dest_if_id_nl.item(0); + String s_dest_if_id = getCharacterDataFromElement(dest_if_id_el); + log.debug("Edge Dest if_id: " + s_dest_if_id); + int dst_if_id = Integer.parseInt(s_dest_if_id); + + //router_id_domain_ed + //edge.setDomain_src_router(source_domain_id); + + edge.setSrc_if_id(src_if_id); + edge.setDst_if_id(dst_if_id); + edge.setDomain_src_router(source_domain_id); + //edge.setDomain_dst_router(dest_domain_id); + + edge.setSrc_router_id(s_router_id_addr); + edge.setDst_router_id(d_router_id_addr); + if(domainTEDB.getInterDomainLinks()==null){ + LinkedList interDomainLinks= new LinkedList(); + interDomainLinks.add(edge); + domainTEDB.setInterDomainLinks(interDomainLinks); + log.info("New interdomain link: "+s_router_id_addr.toString()+" --> "+d_router_id_addr.toString()+" learnt "+edge.getLearntFrom());//+"; \n "+edge); + + }else{ + domainTEDB.getInterDomainLinks().add(edge); + log.info("New interdomain link: "+s_router_id_addr.toString()+" --> "+d_router_id_addr.toString()+" learnt "+edge.getLearntFrom());//+"; \n "+edge); + + } + + } + } + + } + log.debug("Info graph edge :: "+graph.edgeSet()); + + } + } catch (Exception e) { + e.printStackTrace(); + } + + return TEDBs; + } + + + private static TE_Information readTE_INFOfromXml(TE_Information tE_info_common,Element element, Boolean commonBitmapLabelSet, int numLabels, int grid, int cs, int n, int lambdaIni, int lambdaEnd) { + + TE_Information tE_info= new TE_Information(); + if (commonBitmapLabelSet){ + if(lambdaEnd!=Integer.MAX_VALUE) + tE_info.createBitmapLabelSet(numLabels, grid, cs, n,lambdaIni,lambdaEnd); + else + tE_info.createBitmapLabelSet(numLabels, grid, cs, n); + } + + NodeList maximum_bandwidth_nl = element.getElementsByTagName("maximum_bandwidth"); + if (maximum_bandwidth_nl!=null){ + if (maximum_bandwidth_nl.getLength()>0){ + Element maximum_bandwidth_el = (Element) maximum_bandwidth_nl.item(0); + String s_maximum_bandwidth = getCharacterDataFromElement(maximum_bandwidth_el); + + float maximum_bandwidth=Float.parseFloat(s_maximum_bandwidth); + MaximumBandwidth maximumBandwidth =new MaximumBandwidth(); + maximumBandwidth.setMaximumBandwidth(maximum_bandwidth); + tE_info.setMaximumBandwidth(maximumBandwidth); + + } + }else if(tE_info_common!=null && tE_info_common.getMaximumBandwidth()!=null){ + MaximumBandwidth maximumBandwidth =new MaximumBandwidth(); + maximumBandwidth.setMaximumBandwidth(tE_info_common.getMaximumBandwidth().getMaximumBandwidth()); + tE_info.setMaximumBandwidth(maximumBandwidth); + } + /** + * NodeList SID_aux = element.getElementsByTagName("sid"); + Element SID_e = (Element) SID_aux.item(0); + if (SID_e!=null) + { + log.info("SID existe"); + int SID = Integer.parseInt(getCharacterDataFromElement(SID_e)); + SIDS.put(router_id_addr,SID); + log.info("SID of node: "+SID); + } + else + { + log.info("SID not found"); + } + */ + + NodeList defaultmetric = element.getElementsByTagName("default_te_metric"); + Element metric_aux = (Element) defaultmetric.item(0); + + if (metric_aux != null){ + String s_metric_aux = getCharacterDataFromElement(metric_aux); + int metric = Integer.parseInt(s_metric_aux); + DefaultTEMetricLinkAttribTLV defaultTeMetric= new DefaultTEMetricLinkAttribTLV(); + defaultTeMetric.setLinkMetric((long)metric); + tE_info.setDefaultTEMetric(defaultTeMetric); + }else if(tE_info_common!=null && tE_info_common.getDefaultTEMetric()!=null){ + DefaultTEMetricLinkAttribTLV defaultTeMetric= new DefaultTEMetricLinkAttribTLV(); + defaultTeMetric.setLinkMetric(tE_info_common.getDefaultTEMetric().getLinkMetric()); + tE_info.setDefaultTEMetric(defaultTeMetric); + } + + NodeList unreserved_bandwidth_nl = element.getElementsByTagName("unreserved_bandwidth"); + if (unreserved_bandwidth_nl!=null){ + int num_u_b=unreserved_bandwidth_nl.getLength(); + UnreservedBandwidth unreservedBandwidth; + if (num_u_b>0){ + unreservedBandwidth =new UnreservedBandwidth(); + tE_info.setUnreservedBandwidth(unreservedBandwidth); + for(int k=0;k0){ + Element number_wlan_el = (Element) maximum_wlans_nl.item(0); + String s_number_wlans = getCharacterDataFromElement(number_wlan_el); + + int number_wlans=Integer.parseInt(s_number_wlans.replace("\n", "").replaceAll("\\s","")); + tE_info.setNumberWLANs(number_wlans); + tE_info.initWLANs(); + } + } + + NodeList undirDelayLinks = element.getElementsByTagName("undir_delay_link"); + Element undirDelayLink = (Element) undirDelayLinks.item(0); + + if (undirDelayLink != null){ + String s_undirDelayLink = getCharacterDataFromElement(undirDelayLink); + int undirDelayLinkValue = Integer.parseInt(s_undirDelayLink); + UndirectionalLinkDelayDescriptorSubTLV uldSTLV = new UndirectionalLinkDelayDescriptorSubTLV(); + uldSTLV.setDelay(undirDelayLinkValue); + tE_info.setUndirLinkDelay(uldSTLV); + }else if(tE_info_common!=null && tE_info_common.getUndirLinkDelay()!=null){ + UndirectionalLinkDelayDescriptorSubTLV uldSTLV = new UndirectionalLinkDelayDescriptorSubTLV(); + uldSTLV.setDelay(tE_info_common.getUndirLinkDelay().getDelay()); + tE_info.setUndirLinkDelay(uldSTLV); + } + + NodeList undirDelayVars = element.getElementsByTagName("undir_delay_variation"); + Element undirDelayVar = (Element) undirDelayVars.item(0); + if (undirDelayVar != null){ + String s_undirDelayVar = getCharacterDataFromElement(undirDelayVar); + int undirDelayVarValue = Integer.parseInt(s_undirDelayVar); + UndirectionalDelayVariationDescriptorSubTLV udvSTLV = new UndirectionalDelayVariationDescriptorSubTLV(); + udvSTLV.setDelayVar(undirDelayVarValue); + tE_info.setUndirDelayVar(udvSTLV); + }else if(tE_info_common!=null && tE_info_common.getUndirDelayVar()!=null){ + UndirectionalDelayVariationDescriptorSubTLV uldSTLV = new UndirectionalDelayVariationDescriptorSubTLV(); + uldSTLV.setDelayVar(tE_info_common.getUndirDelayVar().getDelayVar()); + tE_info.setUndirDelayVar(uldSTLV); + } + + NodeList undirLinkLosss = element.getElementsByTagName("undir_link_loss"); + Element undirLinkLoss = (Element) undirLinkLosss.item(0); + if (undirLinkLoss != null){ + String s_undirLinkLoss = getCharacterDataFromElement(undirLinkLoss); + int undirLinkLossValue = Integer.parseInt(s_undirLinkLoss); + UndirectionalLinkLossDescriptorSubTLV uSTLV = new UndirectionalLinkLossDescriptorSubTLV(); + uSTLV.setLinkLoss(undirLinkLossValue); + tE_info.setUndirLinkLoss(uSTLV); + }else if(tE_info_common!=null && tE_info_common.getUndirLinkLoss()!=null){ + UndirectionalLinkLossDescriptorSubTLV uldSTLV = new UndirectionalLinkLossDescriptorSubTLV(); + uldSTLV.setLinkLoss(tE_info_common.getUndirLinkLoss().getLinkLoss()); + tE_info.setUndirLinkLoss(uldSTLV); + } + + NodeList undirReBws = element.getElementsByTagName("undir_residual_bandwidth"); + Element undirReBw = (Element) undirReBws.item(0); + if (undirReBw != null){ + String s_undirReBw = getCharacterDataFromElement(undirReBw); + int undirReBwValue = Integer.parseInt(s_undirReBw); + UndirectionalResidualBandwidthDescriptorSubTLV uSTLV = new UndirectionalResidualBandwidthDescriptorSubTLV(); + uSTLV.setResidualBw(undirReBwValue); + tE_info.setUndirResidualBw(uSTLV); + }else if(tE_info_common!=null && tE_info_common.getUndirResidualBw()!=null){ + UndirectionalResidualBandwidthDescriptorSubTLV uldSTLV = new UndirectionalResidualBandwidthDescriptorSubTLV(); + uldSTLV.setResidualBw( tE_info_common.getUndirResidualBw().getResidualBw()); + tE_info.setUndirResidualBw(uldSTLV); + } + + NodeList undirAvalBws = element.getElementsByTagName("undir_available_bandwidth"); + Element undirAvalBw = (Element) undirAvalBws.item(0); + if (undirAvalBw != null){ + String s_undirAvalBw = getCharacterDataFromElement(undirAvalBw); + int undirAvalBwValue = Integer.parseInt(s_undirAvalBw); + UndirectionalAvailableBandwidthDescriptorSubTLV uSTLV = new UndirectionalAvailableBandwidthDescriptorSubTLV(); + uSTLV.setAvailableBw(undirAvalBwValue); + tE_info.setUndirAvailableBw(uSTLV); + }else if(tE_info_common!=null && tE_info_common.getUndirAvailableBw()!=null){ + UndirectionalAvailableBandwidthDescriptorSubTLV uldSTLV = new UndirectionalAvailableBandwidthDescriptorSubTLV(); + uldSTLV.setAvailableBw( tE_info_common.getUndirAvailableBw().getAvailableBw()); + tE_info.setUndirAvailableBw(uldSTLV); + } + + NodeList undirUtilBws = element.getElementsByTagName("undir_utilized_bandwidth"); + Element undirUtilBw = (Element) undirUtilBws.item(0); + if (undirUtilBw != null){ + String s_undirUtilBw = getCharacterDataFromElement(undirUtilBw); + int undirUtilBwValue = Integer.parseInt(s_undirUtilBw); + UndirectionalUtilizedBandwidthDescriptorSubTLV uSTLV = new UndirectionalUtilizedBandwidthDescriptorSubTLV(); + uSTLV.setUtilizedBw(undirUtilBwValue); + tE_info.setUndirUtilizedBw(uSTLV); + }else if(tE_info_common!=null && tE_info_common.getUndirUtilizedBw()!=null){ + UndirectionalUtilizedBandwidthDescriptorSubTLV uldSTLV = new UndirectionalUtilizedBandwidthDescriptorSubTLV(); + uldSTLV.setUtilizedBw( tE_info_common.getUndirUtilizedBw().getUtilizedBw()); + tE_info.setUndirUtilizedBw(uldSTLV); + } + + NodeList minMaxDelays = element.getElementsByTagName("undir_min_max_delay"); + Element minMaxDelay = (Element) minMaxDelays.item(0); + if (minMaxDelay != null){ + NodeList minDelays = minMaxDelay.getElementsByTagName("min"); + Element minDelay = (Element) minDelays.item(0); + NodeList maxDelays = minMaxDelay.getElementsByTagName("max"); + Element maxDelay = (Element) maxDelays.item(0); + if(minDelay !=null && maxDelay!=null){ + String s_minDelay = getCharacterDataFromElement(minDelay); + String s_maxDelay = getCharacterDataFromElement(maxDelay); + int minDelayValue = Integer.parseInt(s_minDelay); + int maxDelayValue = Integer.parseInt(s_maxDelay); + MinMaxUndirectionalLinkDelayDescriptorSubTLV ummSTLV = new MinMaxUndirectionalLinkDelayDescriptorSubTLV(); + ummSTLV.setHighDelay(maxDelayValue); + ummSTLV.setLowDelay(minDelayValue); + tE_info.setMinMaxUndirLinkDelay(ummSTLV); + } + }else if(tE_info_common!=null && tE_info_common.getMinMaxUndirLinkDelay()!=null){ + MinMaxUndirectionalLinkDelayDescriptorSubTLV uldSTLV = new MinMaxUndirectionalLinkDelayDescriptorSubTLV(); + uldSTLV.setHighDelay( tE_info_common.getMinMaxUndirLinkDelay().getHighDelay()); + uldSTLV.setLowDelay( tE_info_common.getMinMaxUndirLinkDelay().getLowDelay()); + tE_info.setMinMaxUndirLinkDelay(uldSTLV); + } + + return tE_info; + + } + + public static SimpleDirectedWeightedGraph readITNetwork(String fileName){ + Logger log=LoggerFactory.getLogger("BGP4Peer"); + SimpleDirectedWeightedGraph graph =new SimpleDirectedWeightedGraph(IntraDomainEdge.class); + Object router_id_addr = null; + Object it_site_id_addr = null; + Object resource_addr = null; + Object s_id_addr = null; + Object d_id_addr = null; + Object s_router_id_addr = null; + Object d_router_id_addr = null; + Object s_it_site_id_addr = null; + Object d_it_site_id_addr = null; + Object s_resource_id_addr = null; + Object d_resource_id_addr = null; + + log.debug("2. SimpleDirectedWeightedGraph"); + + File file = new File(fileName); + try { + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document doc = builder.parse(file); + NodeList nodes_domains = doc.getElementsByTagName("domain"); + HashMapSIDS = new HashMap(); + HashMapSIDSDP = new HashMap(); + + for (int j = 0; j < nodes_domains.getLength(); j++) { + Element element_domain = (Element) nodes_domains.item(j); + NodeList nodes_domain_id = element_domain.getElementsByTagName("domain_id"); + for (int k = 0; k < nodes_domain_id.getLength(); k++) { + Element domain_id_e = (Element) nodes_domain_id.item(0); + String domain_id=getCharacterDataFromElement(domain_id_e); + log.debug("Network domain: "+domain_id); + } + + NodeList nodes = doc.getElementsByTagName("node"); + for (int i = 0; i < nodes.getLength(); i++) { + Element element = (Element) nodes.item(i); + NodeList router_id_node = element.getElementsByTagName("router_id"); + Element router_id_e = (Element) router_id_node.item(0); + String router_id=getCharacterDataFromElement(router_id_e); + log.debug("El router_id es "+router_id); + + try { // router_id_addr type: Inet4Address + router_id_addr = (Inet4Address) Inet4Address.getByName(router_id); + } catch (Exception e) { // router_id_addr type: DataPathID + router_id_addr = DataPathID.getByName(router_id); + } + + graph.addVertex(router_id_addr); + + Element SID_e = (Element) element.getElementsByTagName("sid"); + if (SID_e!=null) + { int SID = Integer.parseInt(getCharacterDataFromElement(SID_e)); + + try { // router_id_addr type: Inet4Address + SIDS.put((Inet4Address)router_id_addr,SID); + } catch (Exception e) { // router_id_addr type: DataPathID + SIDSDP.put((DataPathID)router_id_addr,SID); + } + } + } + + NodeList it_sites = doc.getElementsByTagName("it_site"); + for (int i = 0; i < it_sites.getLength(); i++) { + Element element = (Element) it_sites.item(i); + NodeList it_site_id_node = element.getElementsByTagName("it_site_id"); + Element it_site_id_e = (Element) it_site_id_node.item(0); + String it_site_id=getCharacterDataFromElement(it_site_id_e); + log.debug("El IT_site_id es "+it_site_id); + + try { // it_site_id_addr type: Inet4Address + it_site_id_addr = (Inet4Address) Inet4Address.getByName(it_site_id); + } catch (Exception e) { // it_site_id_addr type: DataPathID + it_site_id_addr = DataPathID.getByName(it_site_id); + } + graph.addVertex(it_site_id_addr); + } + + NodeList storages = doc.getElementsByTagName("storage"); + for (int i = 0; i < storages.getLength(); i++) { + Element element = (Element) storages.item(i); + NodeList resource_id_node = element.getElementsByTagName("resource_id"); + Element resource_id_e = (Element) resource_id_node.item(0); + String resource_id=getCharacterDataFromElement(resource_id_e); + log.debug("El resource_id es "+resource_id); + + try { + resource_addr = (Inet4Address) Inet4Address.getByName(resource_id); + } catch (Exception e) { + resource_addr = DataPathID.getByName(resource_id); + } + graph.addVertex(resource_addr); + } + + NodeList edges = doc.getElementsByTagName("edge"); + for (int i = 0; i < edges.getLength(); i++) { + + Element element = (Element) edges.item(i); + + // We only want those routers which have type="intradomain" //MARTA + if (element.getAttributeNode("type").getValue().equals("intradomain")) {//MARTA + //IntraDomainEdge edge = new IntraDomainEdge(); + + IntraDomainEdge edge = new IntraDomainEdge(); + + NodeList source = element.getElementsByTagName("source"); + Element source_router_el = (Element)source.item(0); + NodeList source_router_id= source_router_el.getElementsByTagName("router_id"); + if (source_router_id.getLength()>0){ + Element source_router_id_el=(Element)source_router_id.item(0); + String s_r_id=getCharacterDataFromElement(source_router_id_el); + + try { // s_router_id_addr type: Inet4Address + s_router_id_addr = (Inet4Address) Inet4Address.getByName(s_r_id); + } catch (Exception e) { // s_router_id_addr type: DataPathID + s_router_id_addr = DataPathID.getByName(s_r_id); + } + + s_id_addr=s_router_id_addr; + } + + NodeList source_it_site_id= source_router_el.getElementsByTagName("it_site_id"); + if (source_it_site_id.getLength()>0){ + Element source_it_site_id_el=(Element)source_it_site_id.item(0); + String s_itsite_id=getCharacterDataFromElement(source_it_site_id_el); + log.debug("Edge Source IT_site_id: "+s_itsite_id); + + try { // s_it_site_id_addr type: Inet4Address + s_it_site_id_addr = (Inet4Address) Inet4Address.getByName(s_itsite_id); + } catch (Exception e) { // s_it_site_id_addr type: DataPathID + s_it_site_id_addr = DataPathID.getByName(s_itsite_id); + } + s_id_addr=s_it_site_id_addr; + } + + NodeList source_resource_id= source_router_el.getElementsByTagName("resource_id"); + if (source_resource_id.getLength()>0){ + Element source_resource_id_el=(Element)source_resource_id.item(0); + String s_resource_id=getCharacterDataFromElement(source_resource_id_el); + log.debug("Edge Source resource_id: "+s_resource_id); + + try {// s_resource_id_addr type: Inet4Address + s_resource_id_addr = (Inet4Address) Inet4Address.getByName(s_resource_id); + } catch (Exception e) { // s_resource_id_addr type: DataPathID + s_resource_id_addr = DataPathID.getByName(s_resource_id); + } + s_id_addr=s_resource_id_addr; + } + + NodeList source_if_id_nl= source_router_el.getElementsByTagName("if_id"); + Element source_if_id_el=(Element)source_if_id_nl.item(0); + String s_source_if_id=getCharacterDataFromElement(source_if_id_el); + log.debug("Edge Source if_id: "+s_source_if_id); + int src_if_id=Integer.parseInt(s_source_if_id); + + + + NodeList dest_nl = element.getElementsByTagName("destination"); + Element dest_el = (Element)dest_nl.item(0); + NodeList dest_router_id_nl= dest_el.getElementsByTagName("router_id"); + if (dest_router_id_nl.getLength()>0){ + Element dest_router_id_el=(Element)dest_router_id_nl.item(0); + String d_r_id=getCharacterDataFromElement(dest_router_id_el); + log.debug("Edge Destination router_id: "+d_r_id); + + try { // d_router_id_addr type: Inet4Address + d_router_id_addr = (Inet4Address) Inet4Address.getByName(d_r_id); + } catch (Exception e) { // d_router_id_addr type: DataPathID + d_router_id_addr = DataPathID.getByName(d_r_id); + + } + d_id_addr=d_router_id_addr; + } + + + NodeList dest_it_site_id_nl= dest_el.getElementsByTagName("it_site_id"); + if (dest_it_site_id_nl.getLength()>0){ + Element dest_it_site_id_el=(Element)dest_it_site_id_nl.item(0); + String d_it_site_id=getCharacterDataFromElement(dest_it_site_id_el); + log.debug("Edge Destination IT_site_id: "+d_it_site_id); + + try { // d_it_site_id_addr type: Inet4Address + d_it_site_id_addr = (Inet4Address) Inet4Address.getByName(d_it_site_id); + } catch (Exception e) { // d_it_site_id_addr type: DataPathID + d_it_site_id_addr = DataPathID.getByName(d_it_site_id); + } + d_id_addr=d_it_site_id_addr; + } + + NodeList dest_resource_id_nl= dest_el.getElementsByTagName("resource_id"); + if (dest_resource_id_nl.getLength()>0){ + Element dest_resource_id_el=(Element)dest_resource_id_nl.item(0); + String d_resource_id=getCharacterDataFromElement(dest_resource_id_el); + log.debug("Edge Destination resource_id: "+d_resource_id); + try { // d_resource_id_addr type: Inet4Address + d_resource_id_addr = (Inet4Address) Inet4Address.getByName(d_resource_id); + } catch (Exception e) { // d_resource_id_addr type: DataPathID + d_resource_id_addr = DataPathID.getByName(d_resource_id); + + } + d_id_addr=d_resource_id_addr; + } + + NodeList dest_if_id_nl= dest_el.getElementsByTagName("if_id"); + Element dest_if_id_el=(Element)dest_if_id_nl.item(0); + String s_dest_if_id=getCharacterDataFromElement(dest_if_id_el); + log.debug("Edge Dest if_id: "+s_dest_if_id); + int dst_if_id=Integer.parseInt(s_dest_if_id); + + + edge.setSrc_if_id(src_if_id); + edge.setDst_if_id(dst_if_id); + + + //TODO: Tal vez pete aqui + //Anyadimos los SID + if (SIDS.get(s_id_addr)!=null && SIDS.get(d_id_addr)!=null) + { + edge.setSrc_sid(SIDS.get(s_id_addr)); + edge.setSrc_sid(SIDS.get(d_id_addr)); + } + + graph.addEdge(s_id_addr, d_id_addr,edge); + }//MARTA + } + } + } + catch (Exception e) { + e.printStackTrace(); + } + + return graph; + } + + + public static Inet4Address readNetworkDomain(String fileName) { + Logger log = LoggerFactory.getLogger("BGP4Peer"); + File file = new File(fileName); + try { + DocumentBuilder builder = DocumentBuilderFactory.newInstance() + .newDocumentBuilder(); + Document doc = builder.parse(file); + + NodeList nodes_domains = doc.getElementsByTagName("domain"); + Element element_domain = (Element) nodes_domains.item(0); + NodeList nodes_domain_id = element_domain.getElementsByTagName("domain_id"); + Element domain_id_e = (Element) nodes_domain_id.item(0); + String domain_id = getCharacterDataFromElement(domain_id_e); + log.info("Network domain: " + domain_id); + Inet4Address domId = (Inet4Address) Inet4Address + .getByName(domain_id); + return domId; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public static String getCharacterDataFromElement(Element e) { + Node child = e.getFirstChild(); + if (child instanceof CharacterData) { + CharacterData cd = (CharacterData) child; + return cd.getData(); + } else { + return "?"; + } + } + + /** + * Reads the inter-domain Topology from a topology XML file. + * Needs update to work with datapath IDs. + * @param fileName Name of the XML + * @return Graph of the network. + */ + public static DirectedWeightedMultigraph readMDNetwork( + String fileName) { + Logger log = LoggerFactory.getLogger("BGP4Peer"); + DirectedWeightedMultigraph graph = new DirectedWeightedMultigraph( + InterDomainEdge.class); + Hashtable router_id_domain_ed = new Hashtable(); + Hashtable router_id_domain_ed_dp = new Hashtable(); + + HashMapSIDS = new HashMap(); + HashMapSIDSDP = new HashMap(); + + Object router_id_addr = null; + Object s_router_id_addr = null; + Object d_router_id_addr = null; + + File file = new File(fileName); + try { + DocumentBuilder builder = DocumentBuilderFactory.newInstance() + .newDocumentBuilder(); + Document doc = builder.parse(file); + + NodeList nodes_domains = doc.getElementsByTagName("domain"); + // First pass to read all the nodes and domains + log.info("Multidomain Graph"); + for (int j = 0; j < nodes_domains.getLength(); j++) { + Element element_domain = (Element) nodes_domains.item(j); + NodeList nodes_domain_id = element_domain + .getElementsByTagName("domain_id"); + Element domain_id_e = (Element) nodes_domain_id.item(0); + String domain_id_str = getCharacterDataFromElement(domain_id_e); + Inet4Address domain_id = (Inet4Address) Inet4Address + .getByName(domain_id_str); + + log.info("Adding Domain: " + domain_id); + graph.addVertex(domain_id); + NodeList nodes = element_domain.getElementsByTagName("node"); + for (int i = 0; i < nodes.getLength(); i++) { + Element element = (Element) nodes.item(i); + NodeList router_id_node = element + .getElementsByTagName("router_id"); + Element router_id_e = (Element) router_id_node.item(0); + String router_id = getCharacterDataFromElement(router_id_e); + log.debug("Router_id: " + router_id); + try { // router_id_addr type: Inet4Address + router_id_addr = (Inet4Address) Inet4Address.getByName(router_id); + } catch (Exception e) { // router_id_addr type: DataPathID + router_id_addr = DataPathID.getByName(router_id); + } + router_id_domain_ed.put(router_id_addr, domain_id); + NodeList nl_sid=element.getElementsByTagName("sid"); + + Element SID_e = (Element) nl_sid.item(0); + if (SID_e!=null) + { int SID = Integer.parseInt(getCharacterDataFromElement(SID_e)); + try { + SIDS.put((Inet4Address)router_id_addr,SID); + } catch (Exception e) { + SIDSDP.put((DataPathID)router_id_addr,SID); + } + } + } + + } + log.debug("Domain_ids read"); + + int numLabels=0; + + Boolean commonBitmapLabelSet = false; + NodeList edgeCommon = doc.getElementsByTagName("edgeCommon"); + int grid=0; + int cs=0; + int n=0; + for (int i = 0; i < edgeCommon.getLength(); i++) { + + Element edgeCommonElement = (Element) edgeCommon.item(i); + NodeList availableLabels_node = edgeCommonElement.getElementsByTagName("AvailableLabels"); + for (int k = 0; k < availableLabels_node.getLength(); k++) { + + Element availableLabels_e = (Element) availableLabels_node.item(k); + NodeList labelSetField_node = availableLabels_e.getElementsByTagName("LabelSetField"); + Element labelSetField_el = (Element) labelSetField_node.item(0); + if (labelSetField_el.getAttributeNode("type").getValue().equals("4")){//Tengo BitMapSet + //Crear un BitMapSet + + NodeList numbLabels_node = labelSetField_el.getElementsByTagName("numLabels"); + + Element numbLabels_e = (Element) numbLabels_node.item(0); + String numbLabels_s = getCharacterDataFromElement(numbLabels_e); + numLabels=Integer.parseInt(numbLabels_s); + + NodeList baseLabel_node = labelSetField_el.getElementsByTagName("baseLabel"); + Element baseLabel_e = (Element) baseLabel_node.item(0); + + float min_frequency; + + grid= Integer.parseInt(baseLabel_e.getAttributeNode("grid").getValue()); + + cs = Integer.parseInt(baseLabel_e.getAttributeNode("cs").getValue()); + boolean n_frequency_included=false; + if (baseLabel_e.getAttributeNode("n") != null ){ + n = Integer.parseInt(baseLabel_e.getAttributeNode("n").getValue()); + n_frequency_included = true; + } + else if (baseLabel_e.getAttributeNode("min_frequency") != null){ + String s_min_frequency = labelSetField_el.getAttributeNode("min_frequency").getValue(); + + min_frequency=Float.parseFloat(s_min_frequency); + n = ((int)min_frequency - 1471)/20; + n_frequency_included=true; + } + if (n_frequency_included){ + commonBitmapLabelSet = true; + }else{ + log.error("ERROR reading the xml file of the topology, you should enter "); + } + + } + } + + } + NodeList edges = doc.getElementsByTagName("edge"); + boolean a =true; + for (int i = 0; i < edges.getLength(); i++) { + log.debug("Looking at edge"); + + Element element = (Element) edges.item(i); + InterDomainEdge edge = new InterDomainEdge(); + TE_Information tE_info=readTE_INFOfromXml(null, element, false,numLabels, grid, cs, n, 0, Integer.MAX_VALUE); + edge.setTE_info(tE_info); + NodeList source = element.getElementsByTagName("source"); + Element source_router_el = (Element) source.item(0); + NodeList source_router_id = source_router_el + .getElementsByTagName("router_id"); + Element source_router_id_el = (Element) source_router_id + .item(0); + String s_r_id = getCharacterDataFromElement(source_router_id_el); + log.debug("Edge Source router_id: " + s_r_id); + + try { // s_router_id_addr type: Inet4Address + s_router_id_addr = (Inet4Address) Inet4Address.getByName(s_r_id); + } catch (Exception e) {// s_router_id_addr type: DataPathID + s_router_id_addr = DataPathID.getByName(s_r_id); + } + Inet4Address source_domain_id = router_id_domain_ed.get(s_router_id_addr); + log.debug("Edge Source domain_id: " + source_domain_id); + + NodeList source_if_id_nl = source_router_el + .getElementsByTagName("if_id"); + Element source_if_id_el = (Element) source_if_id_nl.item(0); + String s_source_if_id = getCharacterDataFromElement(source_if_id_el); + log.debug("Edge Source if_id: " + s_source_if_id); + int src_if_id = Integer.parseInt(s_source_if_id); + + NodeList dest_nl = element.getElementsByTagName("destination"); + Element dest_el = (Element) dest_nl.item(0); + NodeList dest_router_id_nl = dest_el + .getElementsByTagName("router_id"); + Element dest_router_id_el = (Element) dest_router_id_nl.item(0); + String d_r_id = getCharacterDataFromElement(dest_router_id_el); + log.debug("Edge Destination router_id: " + d_r_id); + try { // d_router_id_addr type: Inet4Address + d_router_id_addr = (Inet4Address) Inet4Address.getByName(d_r_id); + } catch (Exception e) { // d_router_id_addr type: DataPathID + d_router_id_addr = DataPathID.getByName(d_r_id); + } + Inet4Address dest_domain_id = router_id_domain_ed.get(d_router_id_addr); + log.debug("Destination domain_id: " + dest_domain_id); + + NodeList dest_if_id_nl = dest_el.getElementsByTagName("if_id"); + Element dest_if_id_el = (Element) dest_if_id_nl.item(0); + String s_dest_if_id = getCharacterDataFromElement(dest_if_id_el); + log.debug("Edge Dest if_id: " + s_dest_if_id); + int dst_if_id = Integer.parseInt(s_dest_if_id); + + //router_id_domain_ed + //edge.setDomain_src_router(source_domain_id); + + edge.setSrc_if_id(src_if_id); + edge.setDst_if_id(dst_if_id); + edge.setDomain_src_router(source_domain_id); + edge.setDomain_dst_router(dest_domain_id); + + edge.setSrc_router_id(s_router_id_addr); + edge.setDst_router_id(d_router_id_addr); + if (!source_domain_id.equals(dest_domain_id)) { + log.info("Adding interdomain link "+source_domain_id.toString()+"-->"+dest_domain_id.toString());//edge.toString()); + //Only add if the source and destination domains are different + graph.addEdge(source_domain_id, dest_domain_id, edge); + } + + } + + + } catch (Exception e) { + e.printStackTrace(); + } + + return graph; + + } + + public static DirectedWeightedMultigraph readMDNetwork( + String fileName, String LearntFrom) { + Logger log = LoggerFactory.getLogger("BGP4Peer"); + DirectedWeightedMultigraph graph = new DirectedWeightedMultigraph( + InterDomainEdge.class); + Hashtable router_id_domain_ed = new Hashtable(); + Hashtable router_id_domain_ed_dp = new Hashtable(); + + HashMapSIDS = new HashMap(); + HashMapSIDSDP = new HashMap(); + + Object router_id_addr = null; + Object s_router_id_addr = null; + Object d_router_id_addr = null; + + File file = new File(fileName); + try { + DocumentBuilder builder = DocumentBuilderFactory.newInstance() + .newDocumentBuilder(); + Document doc = builder.parse(file); + + NodeList nodes_domains = doc.getElementsByTagName("domain"); + // First pass to read all the nodes and domains + log.info("Multidomain Graph"); + for (int j = 0; j < nodes_domains.getLength(); j++) { + Element element_domain = (Element) nodes_domains.item(j); + NodeList nodes_domain_id = element_domain + .getElementsByTagName("domain_id"); + Element domain_id_e = (Element) nodes_domain_id.item(0); + String domain_id_str = getCharacterDataFromElement(domain_id_e); + Inet4Address domain_id = (Inet4Address) Inet4Address + .getByName(domain_id_str); + + log.info("Adding Domain: " + domain_id); + graph.addVertex(domain_id); + NodeList nodes = element_domain.getElementsByTagName("node"); + for (int i = 0; i < nodes.getLength(); i++) { + Element element = (Element) nodes.item(i); + NodeList router_id_node = element + .getElementsByTagName("router_id"); + Element router_id_e = (Element) router_id_node.item(0); + String router_id = getCharacterDataFromElement(router_id_e); + log.debug("Router_id: " + router_id); + try { // router_id_addr type: Inet4Address + router_id_addr = (Inet4Address) Inet4Address.getByName(router_id); + } catch (Exception e) { // router_id_addr type: DataPathID + router_id_addr = DataPathID.getByName(router_id); + } + router_id_domain_ed.put(router_id_addr, domain_id); + NodeList nl_sid=element.getElementsByTagName("sid"); + + Element SID_e = (Element) nl_sid.item(0); + if (SID_e!=null) + { int SID = Integer.parseInt(getCharacterDataFromElement(SID_e)); + try { + SIDS.put((Inet4Address)router_id_addr,SID); + } catch (Exception e) { + SIDSDP.put((DataPathID)router_id_addr,SID); + } + } + } + + } + log.debug("Domain_ids read"); + + int numLabels=0; + + Boolean commonBitmapLabelSet = false; + NodeList edgeCommon = doc.getElementsByTagName("edgeCommon"); + int grid=0; + int cs=0; + int n=0; + for (int i = 0; i < edgeCommon.getLength(); i++) { + + Element edgeCommonElement = (Element) edgeCommon.item(i); + NodeList availableLabels_node = edgeCommonElement.getElementsByTagName("AvailableLabels"); + for (int k = 0; k < availableLabels_node.getLength(); k++) { + + Element availableLabels_e = (Element) availableLabels_node.item(k); + NodeList labelSetField_node = availableLabels_e.getElementsByTagName("LabelSetField"); + Element labelSetField_el = (Element) labelSetField_node.item(0); + if (labelSetField_el.getAttributeNode("type").getValue().equals("4")){//Tengo BitMapSet + //Crear un BitMapSet + + NodeList numbLabels_node = labelSetField_el.getElementsByTagName("numLabels"); + + Element numbLabels_e = (Element) numbLabels_node.item(0); + String numbLabels_s = getCharacterDataFromElement(numbLabels_e); + numLabels=Integer.parseInt(numbLabels_s); + + NodeList baseLabel_node = labelSetField_el.getElementsByTagName("baseLabel"); + Element baseLabel_e = (Element) baseLabel_node.item(0); + + float min_frequency; + + grid= Integer.parseInt(baseLabel_e.getAttributeNode("grid").getValue()); + + cs = Integer.parseInt(baseLabel_e.getAttributeNode("cs").getValue()); + boolean n_frequency_included=false; + if (baseLabel_e.getAttributeNode("n") != null ){ + n = Integer.parseInt(baseLabel_e.getAttributeNode("n").getValue()); + n_frequency_included = true; + } + else if (baseLabel_e.getAttributeNode("min_frequency") != null){ + String s_min_frequency = labelSetField_el.getAttributeNode("min_frequency").getValue(); + + min_frequency=Float.parseFloat(s_min_frequency); + n = ((int)min_frequency - 1471)/20; + n_frequency_included=true; + } + if (n_frequency_included){ + commonBitmapLabelSet = true; + }else{ + log.error("ERROR reading the xml file of the topology, you should enter "); + } + + } + } + + } + NodeList edges = doc.getElementsByTagName("edge"); + boolean a =true; + for (int i = 0; i < edges.getLength(); i++) { + log.debug("Looking at edge"); + + Element element = (Element) edges.item(i); + InterDomainEdge edge = new InterDomainEdge(); + TE_Information tE_info=readTE_INFOfromXml(null, element, false,numLabels, grid, cs, n, 0, Integer.MAX_VALUE); + edge.setTE_info(tE_info); + edge.setLearntFrom(LearntFrom); + NodeList source = element.getElementsByTagName("source"); + Element source_router_el = (Element) source.item(0); + NodeList source_router_id = source_router_el + .getElementsByTagName("router_id"); + Element source_router_id_el = (Element) source_router_id + .item(0); + String s_r_id = getCharacterDataFromElement(source_router_id_el); + log.debug("Edge Source router_id: " + s_r_id); + + try { // s_router_id_addr type: Inet4Address + s_router_id_addr = (Inet4Address) Inet4Address.getByName(s_r_id); + } catch (Exception e) {// s_router_id_addr type: DataPathID + s_router_id_addr = DataPathID.getByName(s_r_id); + } + Inet4Address source_domain_id = router_id_domain_ed.get(s_router_id_addr); + log.debug("Edge Source domain_id: " + source_domain_id); + + NodeList source_if_id_nl = source_router_el + .getElementsByTagName("if_id"); + Element source_if_id_el = (Element) source_if_id_nl.item(0); + String s_source_if_id = getCharacterDataFromElement(source_if_id_el); + log.debug("Edge Source if_id: " + s_source_if_id); + int src_if_id = Integer.parseInt(s_source_if_id); + + NodeList dest_nl = element.getElementsByTagName("destination"); + Element dest_el = (Element) dest_nl.item(0); + NodeList dest_router_id_nl = dest_el + .getElementsByTagName("router_id"); + Element dest_router_id_el = (Element) dest_router_id_nl.item(0); + String d_r_id = getCharacterDataFromElement(dest_router_id_el); + log.debug("Edge Destination router_id: " + d_r_id); + try { // d_router_id_addr type: Inet4Address + d_router_id_addr = (Inet4Address) Inet4Address.getByName(d_r_id); + } catch (Exception e) { // d_router_id_addr type: DataPathID + d_router_id_addr = DataPathID.getByName(d_r_id); + } + Inet4Address dest_domain_id = router_id_domain_ed.get(d_router_id_addr); + log.debug("Destination domain_id: " + dest_domain_id); + + NodeList dest_if_id_nl = dest_el.getElementsByTagName("if_id"); + Element dest_if_id_el = (Element) dest_if_id_nl.item(0); + String s_dest_if_id = getCharacterDataFromElement(dest_if_id_el); + log.debug("Edge Dest if_id: " + s_dest_if_id); + int dst_if_id = Integer.parseInt(s_dest_if_id); + + //router_id_domain_ed + //edge.setDomain_src_router(source_domain_id); + + edge.setSrc_if_id(src_if_id); + edge.setDst_if_id(dst_if_id); + edge.setDomain_src_router(source_domain_id); + edge.setDomain_dst_router(dest_domain_id); + + edge.setSrc_router_id(s_router_id_addr); + edge.setDst_router_id(d_router_id_addr); + if (!source_domain_id.equals(dest_domain_id)) { + log.info("Adding interdomain link "+source_domain_id.toString()+"-->"+dest_domain_id.toString()+" learnt "+edge.getLearntFrom());//edge.toString()); + //Only add if the source and destination domains are different + graph.addEdge(source_domain_id, dest_domain_id, edge); + } + + } + + + } catch (Exception e) { + e.printStackTrace(); + } + + return graph; + + } + + + public static void initializeReachabilityFromFile(String fileName, + ReachabilityManager rm) { + Logger log = LoggerFactory.getLogger("BGP4Peer"); + log.debug("Initializing reachability from " + fileName); + File file = new File(fileName); + try { + DocumentBuilder builder = DocumentBuilderFactory.newInstance() + .newDocumentBuilder(); + Document doc = builder.parse(file); + + NodeList nodes_domains = doc.getElementsByTagName("domain"); + for (int j = 0; j < nodes_domains.getLength(); j++) { + Element element_domain = (Element) nodes_domains.item(j); + NodeList nodes_domain_id = element_domain + .getElementsByTagName("domain_id"); + Element domain_id_e = (Element) nodes_domain_id.item(0); + String domain_id_str = getCharacterDataFromElement(domain_id_e); + Inet4Address domain_id = (Inet4Address) Inet4Address + .getByName(domain_id_str); + + log.debug("Network domain es: " + domain_id); + + NodeList nodes = element_domain + .getElementsByTagName("reachability_entry"); + log.debug("HAY : " + nodes.getLength()); + + for (int i = 0; i < nodes.getLength(); i++) { + Element element = (Element) nodes.item(i); + NodeList ipv4_address_node = element + .getElementsByTagName("ipv4_address"); + Element ipv4_address_el = (Element) ipv4_address_node + .item(0); + String ipv4_address_str = getCharacterDataFromElement(ipv4_address_el); + log.debug("ipv4_address: " + ipv4_address_str); + Inet4Address ipv4_address = (Inet4Address) Inet4Address + .getByName(ipv4_address_str); + IPv4prefixEROSubobject eroso = new IPv4prefixEROSubobject(); + eroso.setIpv4address(ipv4_address); + NodeList prefix_node = element + .getElementsByTagName("prefix"); + Element prefix_el = (Element) prefix_node.item(0); + String prefix_str = getCharacterDataFromElement(prefix_el); + int prefix = Integer.parseInt(prefix_str); + eroso.setPrefix(prefix); + rm.addEROSubobject(domain_id, eroso); + + } + + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + + // IT update del GEYSERS + + public static DirectedWeightedMultigraph readITMDNetwork(String fileName){ + Logger log=LoggerFactory.getLogger("BGP4Peer"); + DirectedWeightedMultigraphgraph =new DirectedWeightedMultigraph(InterDomainEdge.class); + Hashtable router_id_domain_ed=new Hashtable (); + Hashtable it_site_id_domain_ed2=new Hashtable (); + Hashtable resource_id_domain_ed=new Hashtable (); + + File file = new File(fileName); + try { + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document doc = builder.parse(file); + + NodeList nodes_domains = doc.getElementsByTagName("domain"); + + for (int j = 0; j < nodes_domains.getLength(); j++) { + Element element_domain = (Element) nodes_domains.item(j); + NodeList nodes_domain_id = element_domain.getElementsByTagName("domain_id"); + Element domain_id_e = (Element) nodes_domain_id.item(0); + String domain_id_str=getCharacterDataFromElement(domain_id_e); + Inet4Address domain_id= (Inet4Address) Inet4Address.getByName(domain_id_str); + + log.info("Network domain: "+domain_id); + graph.addVertex(domain_id); + NodeList nodes = element_domain.getElementsByTagName("node"); + for (int i = 0; i < nodes.getLength(); i++) { + Element element = (Element) nodes.item(i); + NodeList router_id_node = element.getElementsByTagName("router_id"); + Element router_id_e = (Element) router_id_node.item(0); + String router_id=getCharacterDataFromElement(router_id_e); + log.debug("El router_id es "+router_id); + Inet4Address router_id_addr= (Inet4Address) Inet4Address.getByName(router_id); + + NodeList domain_id_node = element.getElementsByTagName("domain_id"); + router_id_domain_ed.put(router_id_addr, domain_id); + //graph.addVertex(router_id_addr); + + } + + NodeList ITsites = element_domain.getElementsByTagName("it_site"); + for (int i = 0; i < ITsites.getLength(); i++) { + Element element = (Element) ITsites.item(i); + NodeList it_site_id_node = element.getElementsByTagName("it_site_id"); + Element it_site_id_e = (Element) it_site_id_node.item(0); + String it_site_id=getCharacterDataFromElement(it_site_id_e); + log.info("El it_site_id es "+it_site_id); + Inet4Address it_site_id_addr= (Inet4Address) Inet4Address.getByName(it_site_id); + + NodeList domain_id_node = element.getElementsByTagName("domain_id"); + it_site_id_domain_ed2.put(it_site_id_addr, domain_id); + //graph.addVertex(router_id_addr); + + } + + NodeList storages = element_domain.getElementsByTagName("storage"); + for (int i = 0; i < storages.getLength(); i++) { + Element element = (Element) storages.item(i); + NodeList resource_id_node = element.getElementsByTagName("resource_id"); + Element resource_id_e = (Element) resource_id_node.item(0); + String resource_id=getCharacterDataFromElement(resource_id_e); + log.info("El resource_id es "+resource_id); + Inet4Address resource_id_addr= (Inet4Address) Inet4Address.getByName(resource_id); + + NodeList domain_id_node = element.getElementsByTagName("domain_id"); + resource_id_domain_ed.put(resource_id_addr, domain_id); + //graph.addVertex(router_id_addr); + + } + + + } + + + + NodeList edges = doc.getElementsByTagName("edge"); + for (int i = 0; i < edges.getLength(); i++) { + log.info("New interdomain edge"); + Inet4Address s_router_id_addr= null; + Inet4Address d_router_id_addr= null; + Inet4Address s_itsite_id_addr= null; + Inet4Address d_itsite_id_addr= null; + Inet4Address s_resource_id_addr= null; + Inet4Address d_resource_id_addr= null; + Inet4Address source_domain_id=null; + Inet4Address dest_domain_id=null; + + + Element element = (Element) edges.item(i); + InterDomainEdge edge =new InterDomainEdge(); + + NodeList source = element.getElementsByTagName("source"); + Element source_router_el = (Element)source.item(0); + NodeList source_router_id= source_router_el.getElementsByTagName("router_id"); + if (source_router_id.getLength()>0){ + Element source_router_id_el=(Element)source_router_id.item(0); + String s_r_id=getCharacterDataFromElement(source_router_id_el); + log.info("Edge Source router_id: "+s_r_id); + s_router_id_addr= (Inet4Address) Inet4Address.getByName(s_r_id); + source_domain_id= (Inet4Address)router_id_domain_ed.get(s_router_id_addr); + log.info("Edge Source domain_id: "+source_domain_id); + } + + NodeList source_it_site_id= source_router_el.getElementsByTagName("it_site_id"); + if (source_it_site_id.getLength()>0){ + Element source_it_site_id_el=(Element)source_it_site_id.item(0); + String s_itsite_id=getCharacterDataFromElement(source_it_site_id_el); + log.info("Edge Source it_site_id: "+s_itsite_id); + s_itsite_id_addr= (Inet4Address) Inet4Address.getByName(s_itsite_id); + source_domain_id= (Inet4Address)it_site_id_domain_ed2.get(s_itsite_id_addr); + log.info("Edge Source ITsite domain_id: "+source_domain_id); + } + + NodeList source_resource_id= source_router_el.getElementsByTagName("resource_id"); + if (source_resource_id.getLength()>0){ + Element source_resource_id_el=(Element)source_resource_id.item(0); + String s_resource_id=getCharacterDataFromElement(source_resource_id_el); + log.info("Edge Source resource_id: "+s_resource_id); + s_resource_id_addr= (Inet4Address) Inet4Address.getByName(s_resource_id); + source_domain_id= (Inet4Address)resource_id_domain_ed.get(s_resource_id_addr); + log.info("Edge Source ITsite domain_id: "+source_domain_id); + } + + NodeList source_if_id_nl= source_router_el.getElementsByTagName("if_id"); + Element source_if_id_el=(Element)source_if_id_nl.item(0); + String s_source_if_id=getCharacterDataFromElement(source_if_id_el); + log.info("Edge Source if_id: "+s_source_if_id); + int src_if_id=Integer.parseInt(s_source_if_id); + + NodeList dest_nl = element.getElementsByTagName("destination"); + Element dest_el = (Element)dest_nl.item(0); + NodeList dest_router_id_nl= dest_el.getElementsByTagName("router_id"); + if (dest_router_id_nl.getLength()>0){ + Element dest_router_id_el=(Element)dest_router_id_nl.item(0); + String d_r_id=getCharacterDataFromElement(dest_router_id_el); + log.info("Edge Destination router_id: "+d_r_id); + d_router_id_addr= (Inet4Address) Inet4Address.getByName(d_r_id); + dest_domain_id= (Inet4Address)router_id_domain_ed.get(d_router_id_addr); + log.info("Destination domain_id: "+dest_domain_id); + } + + NodeList dest_it_site_id_nl= dest_el.getElementsByTagName("it_site_id"); + if (dest_it_site_id_nl.getLength()>0){ + Element dest_it_site_id_el=(Element)dest_it_site_id_nl.item(0); + String d_itsite_id=getCharacterDataFromElement(dest_it_site_id_el); + log.info("Edge Destination it_site_id: "+d_itsite_id); + d_itsite_id_addr= (Inet4Address) Inet4Address.getByName(d_itsite_id); + dest_domain_id= (Inet4Address)it_site_id_domain_ed2.get(d_itsite_id_addr); + log.info("Destination ITsite domain_id: "+dest_domain_id); + } + + NodeList dest_resource_id_nl= dest_el.getElementsByTagName("resource_id"); + if (dest_resource_id_nl.getLength()>0){ + Element dest_resource_id_el=(Element)dest_resource_id_nl.item(0); + String d_resource_id=getCharacterDataFromElement(dest_resource_id_el); + log.info("Edge Destination resource_id: "+d_resource_id); + d_resource_id_addr= (Inet4Address) Inet4Address.getByName(d_resource_id); + dest_domain_id= (Inet4Address)resource_id_domain_ed.get(d_resource_id_addr); + log.info("Destination ITsite domain_id: "+dest_domain_id); + } + + NodeList dest_if_id_nl= dest_el.getElementsByTagName("if_id"); + Element dest_if_id_el=(Element)dest_if_id_nl.item(0); + String s_dest_if_id=getCharacterDataFromElement(dest_if_id_el); + log.info("Edge Dest if_id: "+s_dest_if_id); + int dst_if_id=Integer.parseInt(s_dest_if_id); + + edge.setSrc_if_id(src_if_id); + edge.setDst_if_id(dst_if_id); + + if (source_router_id.getLength()>0){ + edge.setSrc_router_id(s_router_id_addr); + }else if(source_it_site_id.getLength()>0){ + edge.setSrc_router_id(s_itsite_id_addr); + }else if(source_resource_id.getLength()>0){ + edge.setSrc_router_id(s_resource_id_addr); + } + + if (dest_router_id_nl.getLength()>0){ + edge.setDst_router_id(d_router_id_addr); + }else if(dest_it_site_id_nl.getLength()>0){ + edge.setDst_router_id(d_itsite_id_addr); + }else if(dest_resource_id_nl.getLength()>0){ + edge.setDst_router_id(d_resource_id_addr); + } + graph.addEdge(source_domain_id, dest_domain_id,edge); + } + } + catch (Exception e) { + e.printStackTrace(); + } + + return graph; + + } + + + public static WSONInformation getWSONInformation(String fileName){ + return FileTEDBUpdater.getWSONInformation(fileName,null); + } + + public static WSONInformation getWSONInformation(String fileName, String layer){ + Logger log = LoggerFactory.getLogger("BGP4Peer"); + File file = new File(fileName); + AvailableLabels commonAvailableLabels = null; + WSONInformation WSONinfo = null; + int numLabels = 0; + int grid=0; + int cs=0; + int n=0; + log.debug("FileName:::"+fileName); + try { + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document doc = builder.parse(file); + // NodeList nodes_domains = doc.getElementsByTagName("domain"); + // for (int j = 0; j < nodes_domains.getLength(); j++) { + // Element element_domain = (Element) nodes_domains.item(j); + + NodeList edgeCommon = doc.getElementsByTagName("edgeCommon"); + + for (int i = 0; i < edgeCommon.getLength(); i++) { + + Element edgeCommonElement = (Element) edgeCommon.item(i); + NodeList availableLabels_node = edgeCommonElement.getElementsByTagName("AvailableLabels"); + for (int k = 0; k < availableLabels_node.getLength(); k++) { + commonAvailableLabels = new AvailableLabels(); + Element availableLabels_e = (Element) availableLabels_node.item(k); + NodeList labelSetField_node = availableLabels_e.getElementsByTagName("LabelSetField"); + Element labelSetField_el = (Element) labelSetField_node.item(0); + if (labelSetField_el.getAttributeNode("type").getValue().equals("4")){//Tengo BitMapSet + //Crear un BitMapSet + + NodeList numbLabels_node = labelSetField_el.getElementsByTagName("numLabels"); + + Element numbLabels_e = (Element) numbLabels_node.item(0); + String numbLabels_s = getCharacterDataFromElement(numbLabels_e); + numLabels=Integer.parseInt(numbLabels_s); + + NodeList baseLabel_node = labelSetField_el.getElementsByTagName("baseLabel"); + Element baseLabel_e = (Element) baseLabel_node.item(0); + + float min_frequency; + + grid= Integer.parseInt(baseLabel_e.getAttributeNode("grid").getValue()); + + cs = Integer.parseInt(baseLabel_e.getAttributeNode("cs").getValue()); + boolean n_frequency_included=false; + if (baseLabel_e.getAttributeNode("n") != null ){ + n = Integer.parseInt(baseLabel_e.getAttributeNode("n").getValue()); + n_frequency_included = true; + } + else if (baseLabel_e.getAttributeNode("min_frequency") != null){ + String s_min_frequency = labelSetField_el.getAttributeNode("min_frequency").getValue(); + + min_frequency=Float.parseFloat(s_min_frequency); + n = ((int)min_frequency - 1471)/20; + n_frequency_included=true; + } + if (n_frequency_included){ + createBitmapLabelSet(commonAvailableLabels,numLabels,grid,cs,n); + }else{ + log.error("ERROR reading the xml file of the topology, you should enter "); + } + + } + } + + } + //} + } catch (Exception e) { + log.error(e.toString()); + e.printStackTrace(); + } + if (commonAvailableLabels !=null){ + WSONinfo = new WSONInformation(); + WSONinfo.setCommonAvailableLabels(commonAvailableLabels); + WSONinfo.setNumLambdas(numLabels); + WSONinfo.setCs(cs); + WSONinfo.setGrid(grid); + WSONinfo.setnMin(n); + } + return WSONinfo; + + } + + public static SSONInformation getSSONInformation(String fileName){ + return FileTEDBUpdater.getSSONInformation(fileName,null); + } + + public static SSONInformation getSSONInformation(String fileName, String layer){ + Logger log = LoggerFactory.getLogger("BGP4Peer"); + File file = new File(fileName); + AvailableLabels commonAvailableLabels = null; + SSONInformation SSONinfo = null; + int numLabels = 0; + int grid=0; + int cs=0; + int n=0; + try { + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document doc = builder.parse(file); + // NodeList nodes_domains = doc.getElementsByTagName("domain"); + // for (int j = 0; j < nodes_domains.getLength(); j++) { + // Element element_domain = (Element) nodes_domains.item(j); + + NodeList edgeCommon = doc.getElementsByTagName("edgeCommon"); + + for (int i = 0; i < edgeCommon.getLength(); i++) { + + Element edgeCommonElement = (Element) edgeCommon.item(i); + NodeList availableLabels_node = edgeCommonElement.getElementsByTagName("AvailableLabels"); + for (int k = 0; k < availableLabels_node.getLength(); k++) { + commonAvailableLabels = new AvailableLabels(); + Element availableLabels_e = (Element) availableLabels_node.item(k); + NodeList labelSetField_node = availableLabels_e.getElementsByTagName("LabelSetField"); + Element labelSetField_el = (Element) labelSetField_node.item(0); + if (labelSetField_el.getAttributeNode("type").getValue().equals("4")){//Tengo BitMapSet + //Crear un BitMapSet + + NodeList numbLabels_node = labelSetField_el.getElementsByTagName("numLabels"); + + Element numbLabels_e = (Element) numbLabels_node.item(0); + String numbLabels_s = getCharacterDataFromElement(numbLabels_e); + numLabels=Integer.parseInt(numbLabels_s); + + NodeList baseLabel_node = labelSetField_el.getElementsByTagName("baseLabel"); + Element baseLabel_e = (Element) baseLabel_node.item(0); + + float min_frequency; + + grid= Integer.parseInt(baseLabel_e.getAttributeNode("grid").getValue()); + + cs = Integer.parseInt(baseLabel_e.getAttributeNode("cs").getValue()); + boolean n_frequency_included=false; + if (baseLabel_e.getAttributeNode("n") != null ){ + n = Integer.parseInt(baseLabel_e.getAttributeNode("n").getValue()); + n_frequency_included = true; + } + else if (baseLabel_e.getAttributeNode("min_frequency") != null){ + String s_min_frequency = labelSetField_el.getAttributeNode("min_frequency").getValue(); + + min_frequency=Float.parseFloat(s_min_frequency); + n = ((int)min_frequency - 1471)/20; + n_frequency_included=true; + } + if (n_frequency_included){ + createBitmapLabelSet(commonAvailableLabels,numLabels,grid,cs,n); + }else{ + log.error("ERROR reading the xml file of the topology, you should enter "); + } + + } + } + + } + //} + } catch (Exception e) { + e.printStackTrace(); + } + if (commonAvailableLabels !=null){ + SSONinfo = new SSONInformation(); + SSONinfo.setCommonAvailableLabels(commonAvailableLabels); + // if(cs==5){ + // SSONinfo.setNumLambdas(numLabels*8); + // } + SSONinfo.setNumLambdas(numLabels); + SSONinfo.setCs(cs); + SSONinfo.setGrid(grid); + SSONinfo.setnMin(n); + } + return SSONinfo; + + } + public static void createBitmapLabelSet(AvailableLabels availableLabels,int numLabels,int grid, int cs,int n){ + //FIXME: no hay problema de que se salga el ancho de banda + BitmapLabelSet bitmapLabelSet = new BitmapLabelSet(); + DWDMWavelengthLabel dwdmWavelengthLabel = new DWDMWavelengthLabel(); + dwdmWavelengthLabel.setGrid(grid); + dwdmWavelengthLabel.setChannelSpacing(cs); + dwdmWavelengthLabel.setN(n); + bitmapLabelSet.setDwdmWavelengthLabel(dwdmWavelengthLabel); + + int numberBytes = numLabels/8; + if ((numberBytes*8)>> 24 & 0xFF); + mask[1] = (byte) (maskLong >>> 16 & 0xFF); + mask[2] = (byte) (maskLong >>> 8 & 0xFF); + mask[3] = (byte) (maskLong & 0xFF); + //Meto la mascara + reachabilityEntry.setMask(mask); + + + } + } + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + + + /** + * Read the interdomain Topology from a topology file + * @param fileName Name of the xml file. + * @return List of interdomain edges. + */ + public static LinkedList readInterDomainLinks(String fileName) { + + LinkedList interDomainLinks = new LinkedList(); + Logger log = LoggerFactory.getLogger("BGP4Peer"); + File file = new File(fileName); + Inet4Address domain_id=null; + try { + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document doc = builder.parse(file); + + NodeList nodes_domains = doc.getElementsByTagName("domain"); + if (nodes_domains!=null){ + if (nodes_domains.getLength()>=1){ + for (int j = 0; j < nodes_domains.getLength(); j++) { + Element element_domain = (Element) nodes_domains.item(j); + NodeList nodes_domain_id = element_domain.getElementsByTagName("domain_id"); + Element domain_id_e = (Element) nodes_domain_id.item(0); + String domain_id_str=getCharacterDataFromElement(domain_id_e); + domain_id= (Inet4Address) Inet4Address.getByName(domain_id_str); + } + } + } + + + + Boolean commonBitmapLabelSet = false; + NodeList edgeCommon = doc.getElementsByTagName("edgeCommon"); + int grid=0; + int cs=0; + int n=0; + int numLabels=0; + for (int i = 0; i < edgeCommon.getLength(); i++) { + + Element edgeCommonElement = (Element) edgeCommon.item(i); + NodeList availableLabels_node = edgeCommonElement.getElementsByTagName("AvailableLabels"); + for (int k = 0; k < availableLabels_node.getLength(); k++) { + + Element availableLabels_e = (Element) availableLabels_node.item(k); + NodeList labelSetField_node = availableLabels_e.getElementsByTagName("LabelSetField"); + Element labelSetField_el = (Element) labelSetField_node.item(0); + if (labelSetField_el.getAttributeNode("type").getValue().equals("4")){//Tengo BitMapSet + //Crear un BitMapSet + + NodeList numbLabels_node = labelSetField_el.getElementsByTagName("numLabels"); + + Element numbLabels_e = (Element) numbLabels_node.item(0); + String numbLabels_s = getCharacterDataFromElement(numbLabels_e); + numLabels=Integer.parseInt(numbLabels_s); + + NodeList baseLabel_node = labelSetField_el.getElementsByTagName("baseLabel"); + Element baseLabel_e = (Element) baseLabel_node.item(0); + + float min_frequency; + + grid= Integer.parseInt(baseLabel_e.getAttributeNode("grid").getValue()); + + cs = Integer.parseInt(baseLabel_e.getAttributeNode("cs").getValue()); + boolean n_frequency_included=false; + if (baseLabel_e.getAttributeNode("n") != null ){ + n = Integer.parseInt(baseLabel_e.getAttributeNode("n").getValue()); + n_frequency_included = true; + } + else if (baseLabel_e.getAttributeNode("min_frequency") != null){ + String s_min_frequency = labelSetField_el.getAttributeNode("min_frequency").getValue(); + + min_frequency=Float.parseFloat(s_min_frequency); + n = ((int)min_frequency - 1471)/20; + n_frequency_included=true; + } + if (n_frequency_included){ + commonBitmapLabelSet = true; + }else{ + log.error("ERROR reading the xml file of the topology, you should enter "); + } + + } + } + + } + + + // Read the nodes of the domain which has interdomain connection + NodeList edges = doc.getElementsByTagName("edge"); + for (int i = 0; i < edges.getLength(); i++) { + Element element = (Element) edges.item(i); + + // We only want those routers which have type="interdomain" + //if (((String)element.getAttributeNode("type").getValue()).equals("interdomain")) { + + if (element.getAttributeNode("type")!=null) { + + + if (element.getAttributeNode("type").getValue().equals("interdomain")) { + + // Create a variable InterDomainEdge where we include + // the two nodes of the connection. + InterDomainEdge connection = new InterDomainEdge(); + NodeList source = element.getElementsByTagName("source"); + Element source_router_el = (Element) source.item(0); + //Read the source router IP + NodeList source_router_id = source_router_el.getElementsByTagName("router_id"); + Element source_router_id_el = (Element) source_router_id.item(0); + String s_r_id = getCharacterDataFromElement(source_router_id_el); + + Inet4Address s_router_id_addr = (Inet4Address) Inet4Address.getByName(s_r_id); + //Read the source router interface identifier of the connection + NodeList source_if_id_nl = source_router_el.getElementsByTagName("if_id"); + Element source_if_id_el = (Element) source_if_id_nl.item(0); + String s_source_if_id = getCharacterDataFromElement(source_if_id_el); + + int src_if_id = Integer.parseInt(s_source_if_id); + NodeList src_domain_nl = source_router_el.getElementsByTagName("domain_id"); + Inet4Address s_router_domain=null; + + if (src_domain_nl!=null) + { + if (src_domain_nl.getLength()>=1){ + Element domain_id_el = (Element) src_domain_nl.item(0); + String s_r_domain = getCharacterDataFromElement(domain_id_el).trim(); + s_router_domain = (Inet4Address) Inet4Address.getByName(s_r_domain); + + }else{ + s_router_domain= domain_id; + + } + }else { + s_router_domain= domain_id; + + } + + + + //Read the router destination + NodeList dest_nl = element.getElementsByTagName("destination"); + Element dest_el = (Element) dest_nl.item(0); + NodeList dest_router_id_nl = dest_el.getElementsByTagName("router_id"); + Element dest_router_id_el = (Element) dest_router_id_nl.item(0); + String d_r_id = getCharacterDataFromElement(dest_router_id_el); + log.info("Edge Destination router_id: "+ d_r_id); + Inet4Address d_router_id_addr = (Inet4Address) Inet4Address.getByName(d_r_id); + NodeList dest_if_id_nl = dest_el.getElementsByTagName("if_id"); + Element dest_if_id_el = (Element) dest_if_id_nl.item(0); + String s_dest_if_id = getCharacterDataFromElement(dest_if_id_el); + log.info("Edge Dest if_id: " + s_dest_if_id); + int dst_if_id = Integer.parseInt(s_dest_if_id); + NodeList domain = dest_el.getElementsByTagName("domain_id"); + Element domain_id_el = (Element) domain.item(0); + String d_r_domain = getCharacterDataFromElement(domain_id_el); + log.info("Destination router domain: "+ d_r_domain); + Inet4Address d_router_domain= (Inet4Address) Inet4Address.getByName(d_r_domain); + + + // Include the connection between both nodes + connection.setSrc_if_id(src_if_id); + connection.setSrc_router_id(s_router_id_addr); + connection.setDst_if_id(dst_if_id); + connection.setDst_router_id(d_router_id_addr); + connection.setDomain_src_router(s_router_domain); + connection.setDomain_dst_router(d_router_domain); + if(connection.getTE_info()==null){ + TE_Information tE_info= new TE_Information(); + if (commonBitmapLabelSet){ + tE_info.createBitmapLabelSet(numLabels, grid, cs, n); + } + connection.setTE_info(tE_info); + } + //add the connection to the LinkedList. + interDomainLinks.add(connection); + + } + } + } + //}//end for domains + } catch (Exception e) { + e.printStackTrace(); + } + + return interDomainLinks; + + } + + public static int readWSONLambdas(String fileName){ + Logger log=LoggerFactory.getLogger("BGP4Peer"); + File file = new File(fileName); + int num_wavelengths=4; + try { + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document doc = builder.parse(file); + NodeList nodes_domains = doc.getElementsByTagName("domain"); + + for (int j = 0; j < nodes_domains.getLength(); j++) { + Element element_domain = (Element) nodes_domains.item(j); + NodeList nodes_wl= element_domain.getElementsByTagName("num_wavelengths"); + for (int k = 0; k < nodes_wl.getLength(); k++) { + Element nodes_wl_e = (Element) nodes_wl.item(0); + String num_wavelengths_id=getCharacterDataFromElement(nodes_wl_e ); + num_wavelengths=Integer.parseInt(num_wavelengths_id); + log.info("num_wavelength: "+num_wavelengths); + } + + } + } + catch (Exception e) { + e.printStackTrace(); + } + + return num_wavelengths; + } + + + public static Hashtable getITSites(String fileName){ + Hashtable it_site_id_domain_ed=new Hashtable (); + + File file2 = new File(fileName); + try { + DocumentBuilder builder2 = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document doc2 = builder2.parse(file2); + + NodeList nodes_domains = doc2.getElementsByTagName("domain"); + + for (int j = 0; j < nodes_domains.getLength(); j++) { + Element element_domain = (Element) nodes_domains.item(j); + NodeList nodes_domain_id = element_domain.getElementsByTagName("domain_id"); + Element domain_id_e = (Element) nodes_domain_id.item(0); + String domain_id_str=getCharacterDataFromElement(domain_id_e); + Inet4Address domain_id= (Inet4Address) Inet4Address.getByName(domain_id_str); + + NodeList ITsites = element_domain.getElementsByTagName("it_site"); + for (int i = 0; i < ITsites.getLength(); i++) { + Element element = (Element) ITsites.item(i); + NodeList it_site_id_node = element.getElementsByTagName("it_site_id"); + Element it_site_id_e = (Element) it_site_id_node.item(0); + String it_site_id=getCharacterDataFromElement(it_site_id_e); + Inet4Address it_site_id_addr= (Inet4Address) Inet4Address.getByName(it_site_id); + + NodeList domain_id_node = element.getElementsByTagName("domain_id"); + it_site_id_domain_ed.put(it_site_id_addr, domain_id); + //graph.addVertex(router_id_addr); + } + + } + + } + catch (Exception e) { + e.printStackTrace(); + } + + return it_site_id_domain_ed; + + } + + + public static Hashtable getResource(String fileName){ + Hashtable resource_id_domain_ed=new Hashtable (); + + File file2 = new File(fileName); + try { + DocumentBuilder builder2 = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document doc2 = builder2.parse(file2); + + NodeList nodes_domains = doc2.getElementsByTagName("domain"); + + for (int j = 0; j < nodes_domains.getLength(); j++) { + Element element_domain = (Element) nodes_domains.item(j); + NodeList nodes_domain_id = element_domain.getElementsByTagName("domain_id"); + Element domain_id_e = (Element) nodes_domain_id.item(0); + String domain_id_str=getCharacterDataFromElement(domain_id_e); + Inet4Address domain_id= (Inet4Address) Inet4Address.getByName(domain_id_str); + + NodeList storages = element_domain.getElementsByTagName("storage"); + for (int i = 0; i < storages.getLength(); i++) { + Element element = (Element) storages.item(i); + NodeList resource_id_node = element.getElementsByTagName("resource_id"); + Element resource_id_e = (Element) resource_id_node.item(0); + String resource_id=getCharacterDataFromElement(resource_id_e); + Inet4Address resource_id_addr= (Inet4Address) Inet4Address.getByName(resource_id); + + NodeList domain_id_node = element.getElementsByTagName("domain_id"); + resource_id_domain_ed.put(resource_id_addr, domain_id); + //graph.addVertex(router_id_addr); + + } + + } + + } + catch (Exception e) { + e.printStackTrace(); + } + return resource_id_domain_ed; + + } + + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/IT_Resources.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/IT_Resources.java new file mode 100644 index 000000000..a819bcf4d --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/IT_Resources.java @@ -0,0 +1,147 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb; + +import es.tid.bgp.bgp4.update.tlv.linkstate_attribute_tlvs.DefaultTEMetricLinkAttribTLV; +import es.tid.bgp.bgp4.update.tlv.linkstate_attribute_tlvs.IPv4RouterIDLocalNodeLinkAttribTLV; +import es.tid.bgp.bgp4.update.tlv.linkstate_attribute_tlvs.IPv4RouterIDRemoteNodeLinkAttribTLV; +import es.tid.bgp.bgp4.update.tlv.linkstate_attribute_tlvs.LinkProtectionTypeLinkAttribTLV; +import es.tid.bgp.bgp4.update.tlv.linkstate_attribute_tlvs.MF_OTPAttribTLV; +import es.tid.bgp.bgp4.update.tlv.linkstate_attribute_tlvs.MetricLinkAttribTLV; +import es.tid.bgp.bgp4.update.tlv.linkstate_attribute_tlvs.TransceiverClassAndAppAttribTLV; +import es.tid.bgp.bgp4.update.tlv.node_link_prefix_descriptor_subTLVs.MinMaxUndirectionalLinkDelayDescriptorSubTLV; +import es.tid.bgp.bgp4.update.tlv.node_link_prefix_descriptor_subTLVs.UndirectionalAvailableBandwidthDescriptorSubTLV; +import es.tid.bgp.bgp4.update.tlv.node_link_prefix_descriptor_subTLVs.UndirectionalDelayVariationDescriptorSubTLV; +import es.tid.bgp.bgp4.update.tlv.node_link_prefix_descriptor_subTLVs.UndirectionalLinkDelayDescriptorSubTLV; +import es.tid.bgp.bgp4.update.tlv.node_link_prefix_descriptor_subTLVs.UndirectionalLinkLossDescriptorSubTLV; +import es.tid.bgp.bgp4.update.tlv.node_link_prefix_descriptor_subTLVs.UndirectionalResidualBandwidthDescriptorSubTLV; +import es.tid.bgp.bgp4.update.tlv.node_link_prefix_descriptor_subTLVs.UndirectionalUtilizedBandwidthDescriptorSubTLV; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.AdministrativeGroup; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.AvailableLabels; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.IPv4RemoteASBRID; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.InterfaceSwitchingCapabilityDescriptor; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.LinkLocalRemoteIdentifiers; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.LinkProtectionType; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.MaximumBandwidth; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.MaximumReservableBandwidth; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.RemoteASNumber; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.SharedRiskLinkGroup; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.TrafficEngineeringMetric; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.UnreservedBandwidth; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.complexFields.BitmapLabelSet; +import es.tid.rsvp.constructs.gmpls.DWDMWavelengthLabel; + +public class IT_Resources { + + private String controllerIT; + private String cpu; + private String mem; + private String storage; + private String learntFrom; + private String domainID; + + /** + * TEDB logger + */ + public IT_Resources() + { + //initWLANs(); + } + + public String getCpu() { + return cpu; + } + + public void setCpu(String cpu) { + this.cpu = cpu; + } + + + public String getMem() { + return mem; + } + + public void setMem(String mem) { + this.mem = mem; + } + + + public String getStorage() { + return storage; + } + + public void setStorage(String storage) { + this.storage = storage; + } + + /** + * Funcion que transforma una cantidad de bits en el numero de bytes que necesita + * @param numBit + */ + private int getNumberBytes(int numBits){ + int numberBytes = numBits/8; + if ((numberBytes*8) "+dst_router_id.toString()+":"+dst_if_id+" ("+((Object)super.getTarget()).toString()+")"; + ideString=src_router_id.toString()+": "+src_if_id+" --> "+dst_router_id.toString()+": "+dst_if_id; + /*if (TE_info==null){ + return ideString; + } + else + { + if ((this.TE_info.getAvailableLabels()!=null) &&(this.TE_info.getAvailableLabels().getLabelSet()!=null)){ + ideString=ideString+" Bitmap: {"; + for (int i=0;i"+this.getTarget()+":"+this.getDst_if_id()+" NumFibers = "+numFibers; + if (TE_info==null){ + return ret; + } + else + { + if ((this.TE_info.getAvailableLabels()!=null) &&(this.TE_info.getAvailableLabels().getLabelSet()!=null)){ + ret=ret+" Bitmap: {"; + for (int i=0;i"+this.getTarget()+":"+this.getDst_if_id(); + if (TE_info==null){ + return ret; + } + else + { + if (this.TE_info.getAvailableLabels()!=null){ + ret=ret+" Bitmap: {"; + for (int i=0;i networkDomainGraph; + public SimpleDirectedWeightedGraph networkGraph; + + //private LinkedList interDomainLinks; + + public SimpleTEDB simple_ted; + + private Logger log; + + private boolean addBidirectional; + + /** + * Table with IP address/prefix --> domain + */ + LinkedList reachability; + + public MDTEDB(){ + log=LoggerFactory.getLogger("BGP4Peer"); + networkDomainGraph=new DirectedWeightedMultigraph (InterDomainEdge.class); + addBidirectional=true;//FIXME: ESTO ES UN APA�O TEMPORAL + reachability=new LinkedList(); + //interDomainLinks = new LinkedList(); + } + + public DirectedWeightedMultigraph getDuplicatedMDNetworkGraph(){ + + DirectedWeightedMultigraph graphCopy= (DirectedWeightedMultigraph) networkDomainGraph.clone(); + return graphCopy; + } + + public DirectedWeightedMultigraph getNetworkDomainGraph() { + return networkDomainGraph; + } + + public void setNetworkDomainGraph( + DirectedWeightedMultigraph networkDomainGraph) { + this.networkDomainGraph = networkDomainGraph; + } + + public void initializeFromFile(String file){ + networkDomainGraph=FileTEDBUpdater.readMDNetwork(file); + } + + public void initializeFromFile(String file, String learntFrom){ + networkDomainGraph=FileTEDBUpdater.readMDNetwork(file, learntFrom); + } + + public void initializeFromFileInterDomainLinks(String file){ + } + + public void initializeFullTEDFromFile(String file){ + networkGraph=FileTEDBUpdater.readNetwork(file); + } + + public long getGraphId() { + return graphId; + } + public void setGraphId(long graphId) { + this.graphId = graphId; + } + + + public SimpleDirectedWeightedGraph getDuplicatedNetworkGraph() { + return networkGraph; + } + + public synchronized void addInterdomainLink( Object localDomainID, Object localRouterASBR, long localRouterASBRIf, Object remoteDomainID, Object remoteRouterASBR, long remoteRouterASBRIf, TE_Information te_info){ + + if (!networkDomainGraph.containsVertex(localDomainID)){ + networkDomainGraph.addVertex(localDomainID); + log.debug("Vertex (domain) "+localDomainID+" added"); + } + if (!networkDomainGraph.containsVertex(remoteDomainID)){ + networkDomainGraph.addVertex(remoteDomainID); + log.debug("Vertex (domain) "+remoteDomainID+" added"); + } + log.debug("Looking to add "+localRouterASBR+":"+localRouterASBRIf+" ("+localDomainID+") -->"+remoteRouterASBR+":"+remoteRouterASBRIf+" ("+remoteDomainID+")"); + Set edgeset= networkDomainGraph.edgesOf(localDomainID); + Iterator iterador=edgeset.iterator(); + boolean edgeFound=false; + InterDomainEdge interDomainEdgeFound=null; + if (edgeset.size() == 0) + log.debug("Edge set size = 0"); + while (iterador.hasNext()){ + InterDomainEdge interDomainEdge=iterador.next(); + log.debug("existing edge: "+interDomainEdge.toString()); + if (interDomainEdge.getSrc_router_id().equals(localRouterASBR)){ + log.debug("Local router is the same!!!"); + if (interDomainEdge.getDst_router_id().equals(remoteRouterASBR)){ + log.debug("Destination router is the same!!!"); + edgeFound=true; + interDomainEdgeFound=interDomainEdge; + } + else { + log.debug("Destination router is NOT the same!!!"); + } + }else { + log.debug("Local router is NOT the same!!!"); + } + } + + if (edgeFound==false) { + InterDomainEdge newInterDomainEdge =new InterDomainEdge(); + newInterDomainEdge.setSrc_router_id(localRouterASBR); + newInterDomainEdge.setDst_router_id(remoteRouterASBR); + newInterDomainEdge.setSrc_if_id(localRouterASBRIf); + newInterDomainEdge.setDst_if_id(remoteRouterASBRIf); + newInterDomainEdge.setDomain_dst_router(remoteDomainID); + newInterDomainEdge.setDomain_src_router(localDomainID); + if (te_info != null) + newInterDomainEdge.setTE_info(te_info); + networkDomainGraph.addEdge(localDomainID, remoteDomainID, newInterDomainEdge); + log.info("New interdomain edge between "+localDomainID+" and "+remoteDomainID+" received"); + + }else { + + if (te_info != null){ + //FIXME: Update of TE info to be optimized + log.debug("TE_info updated"); + interDomainEdgeFound.setTE_info(te_info); + } + + + } + } + + + public void addReachabilityIPv4(Inet4Address domainId,Inet4Address aggregatedIPRange,int prefix){ + ReachabilityEntry ra=new ReachabilityEntry(); + ra.setAggregatedIPRange(aggregatedIPRange); + long resta=((long)0x1<>>24 & 0xFF); + mask[1]=(byte)(maskLong>>>16 & 0xFF); + mask[2]=(byte)(maskLong>>>8 & 0xFF); + mask[3]=(byte)(maskLong& 0xFF); + ra.setMask(mask); + ra.setDomainId(domainId); + ra.setPrefix(prefix); + if (!(reachability.contains(ra))){ + reachability.add(ra); + } + return; + } + + + public String printMDTopology(){ + String topoString; + Set vetexSet= networkDomainGraph.vertexSet(); + Iterator vertexIterator=vetexSet.iterator(); + topoString="Domains: \r\n"; + while (vertexIterator.hasNext()){ + Object vertex= vertexIterator.next(); + topoString=topoString+"\t"+vertex.toString()+"\r\n"; + } + topoString=topoString+"Interdomain list: \r\n"; + Set edgeSet= networkDomainGraph.edgeSet(); + Iterator edgeIterator=edgeSet.iterator(); + while (edgeIterator.hasNext()){ + InterDomainEdge edge= edgeIterator.next(); + topoString=topoString+"\t"+edge.toString()+"\r\n"; + } + + return topoString; + } + +// public String printMD2Topology(){ +// String topoString; +// Set vetexSet= networkDomainGraph.vertexSet(); +// Iterator vertexIterator=vetexSet.iterator(); +// topoString="Domains: \r\n"; +// while (vertexIterator.hasNext()){ +// Object vertex= vertexIterator.next(); +// topoString=topoString+"\t"+vertex.toString()+"\r\n"; +// } +// topoString=topoString+"Interdomain list: \r\n"; +// Iterator edgeIterator=interDomainLinks.iterator(); +// while (edgeIterator.hasNext()){ +// InterDomainEdge edge= edgeIterator.next(); +// topoString=topoString+"\t"+edge.toString()+"\r\n"; +// } +// +// return topoString; +// } + + //Check resources SSON and WSON + public boolean CheckLocalResources(long ifID, Object ip){ + Iterator iteredges = networkDomainGraph.edgeSet().iterator(); + InterDomainEdge link; + while (iteredges.hasNext()) + { + link = iteredges.next(); + if ((link.getSrc_if_id()==(ifID))) + { + log.info("InterDomain Link Found to "+link.getDst_router_id().toString()); + return true; + } + } + return false; + } + + @Override + public String printTopology() { + // TODO Auto-generated method stub + return printMDTopology(); + } + + public LinkedList getInterDomainLinks() { + return new LinkedList(networkDomainGraph.edgeSet()); + } + + @Override + public boolean isITtedb() { + // TODO Auto-generated method stub + return false; + } + + public SimpleTEDB getSimple_ted() { + return simple_ted; + } + + public void setSimple_ted(SimpleTEDB simple_ted) { + this.simple_ted = simple_ted; + } + + public LinkedList getReachability() { + return reachability; + } + + public void setReachability(LinkedList reachability) { + this.reachability = reachability; + } + + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MultiDomainTEDB.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MultiDomainTEDB.java new file mode 100644 index 000000000..19c345888 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MultiDomainTEDB.java @@ -0,0 +1,25 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb; + +import java.net.Inet4Address; + + +public interface MultiDomainTEDB extends TEDB { + + public void addInterdomainLink( Object localDomainID, Object localRouterASBR, long localRouterASBRIf, Object remoteDomainID, Object remoteRouterASBR, long remoteRouterASBRIf, TE_Information te_info ); + public void addReachabilityIPv4(Inet4Address domainId,Inet4Address aggregatedIPRange,int prefix); + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MultiLayerTEDB.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MultiLayerTEDB.java new file mode 100644 index 000000000..a2690516a --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/MultiLayerTEDB.java @@ -0,0 +1,473 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb; + +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.complexFields.BitmapLabelSet; +import org.jgrapht.graph.SimpleDirectedWeightedGraph; + +import java.net.Inet4Address; +import java.util.*; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + + +public class MultiLayerTEDB implements DomainTEDB { + + private ArrayList registeredAlgorithms; + /** + * Graph of the Upper Layer Network + */ + /** + * + */ + private SimpleDirectedWeightedGraph upperLayerGraph; + + /** + * Graph of the Upper Layer Network + */ + private SimpleDirectedWeightedGraph lowerLayerGraph; + + /** + * InterLayer Graph + */ + private SimpleDirectedWeightedGraph interLayerGraph; + /** + * Reachability information + */ + private ReachabilityEntry reachabilityEntry; + + /** + * WSON Information of the lower Layer + */ + private WSONInformation WSONinfo=null; + + private Lock TEDBlock; + + + /** + * List of interdomain Links + */ + private LinkedList interDomainLinks; + + private Hashtable RelationNodesInterlayer; + + + + + public MultiLayerTEDB(){ + registeredAlgorithms= new ArrayList(); + TEDBlock=new ReentrantLock(); + } + + + public SimpleDirectedWeightedGraph getUpperLayerGraph() { + return upperLayerGraph; + } + + public void setUpperLayerGraph( + SimpleDirectedWeightedGraph upperLayerGraph) { + this.upperLayerGraph = upperLayerGraph; + } + + + public SimpleDirectedWeightedGraph getLowerLayerGraph() { + return lowerLayerGraph; + } + + public void setLowerLayerGraph( + SimpleDirectedWeightedGraph lowerLayerGraph) { + this.lowerLayerGraph = lowerLayerGraph; + } + + + public SimpleDirectedWeightedGraph getInterLayerGraph() { + return interLayerGraph; + } + + public void setInterLayerGraph( + SimpleDirectedWeightedGraph interLayerGraph) { + this.interLayerGraph = interLayerGraph; + } + + + + public SimpleDirectedWeightedGraph getDuplicatedUpperLayerkGraph(){ + SimpleDirectedWeightedGraph graphCopy; + TEDBlock.lock(); + try{ + graphCopy= (SimpleDirectedWeightedGraph) upperLayerGraph.clone(); + } finally{ + TEDBlock.unlock(); + } + return graphCopy; + } + public Hashtable getRelationNodesInterlayer() { + return RelationNodesInterlayer; + } + public SimpleDirectedWeightedGraph getDuplicatedLowerLayerkGraph(){ + SimpleDirectedWeightedGraph graphCopy; + TEDBlock.lock(); + try{ + graphCopy= (SimpleDirectedWeightedGraph) lowerLayerGraph.clone(); + } finally{ + TEDBlock.unlock(); + } + return graphCopy; + } + + public SimpleDirectedWeightedGraph getDuplicatedInterLayerGraph(){ + SimpleDirectedWeightedGraph graphCopy; + TEDBlock.lock(); + try{ + graphCopy= (SimpleDirectedWeightedGraph) interLayerGraph.clone(); + } finally{ + TEDBlock.unlock(); + } + return graphCopy; + } + + public void initializeFromFile(String file) { + upperLayerGraph=FileTEDBUpdater.readNetwork(file, "mpls"); + lowerLayerGraph=FileTEDBUpdater.readNetwork(file, "wson"); + interLayerGraph=FileTEDBUpdater.readNetwork(file, "interlayer"); + WSONinfo = FileTEDBUpdater.getWSONInformation(file, "wson"); + interDomainLinks = FileTEDBUpdater.readInterDomainLinks(file); + + reachabilityEntry = new ReachabilityEntry(); + //domainReachabilityIPv4Prefix=new byte[4]; + FileTEDBUpdater.getDomainReachabilityFromFile(file,reachabilityEntry,"mpls"); + } + + @Override + public void initializeFromFile(String file, String learnFrom) { + + } + + @Override + public boolean isITtedb() { + // TODO Auto-generated method stub + return false; + } + + @Override + public String printTopology() { + String topoString; + Set vetexSet= upperLayerGraph.vertexSet(); + Iterator vertexIterator=vetexSet.iterator(); + topoString="MPLS Nodes: \r\n"; + while (vertexIterator.hasNext()){ + Object vertex= vertexIterator.next(); + topoString=topoString+"\t"+vertex.toString()+"\r\n"; + } + topoString=topoString+"MPLS Link list: \r\n"; + Set edgeSet= upperLayerGraph.edgeSet(); + Iterator edgeIterator=edgeSet.iterator(); + while (edgeIterator.hasNext()){ + IntraDomainEdge edge= edgeIterator.next(); + topoString=topoString+"\t"+edge.toString()+"\r\n"; + } + vetexSet= lowerLayerGraph.vertexSet(); + vertexIterator=vetexSet.iterator(); + topoString="GMPLS Nodes: \r\n"; + while (vertexIterator.hasNext()){ + Object vertex= vertexIterator.next(); + topoString=topoString+"\t"+vertex.toString()+"\r\n"; + } + topoString=topoString+"gmpls Link list: \r\n"; + edgeSet= lowerLayerGraph.edgeSet(); + edgeIterator=edgeSet.iterator(); + while (edgeIterator.hasNext()){ + IntraDomainEdge edge= edgeIterator.next(); + topoString=topoString+"\t"+edge.toString()+"\r\n"; + } + topoString=topoString+"InterLayer list: \r\n"; + edgeSet= interLayerGraph.edgeSet(); + edgeIterator=edgeSet.iterator(); + while (edgeIterator.hasNext()){ + IntraDomainEdge edge= edgeIterator.next(); + topoString=topoString+"\t"+edge.toString()+"\r\n"; + } + + topoString=topoString+printInterDomainLinks(); + return topoString; + } + + @Override + public boolean belongsToDomain(Object addr) { + int i; + byte[] addrbytes= ((Inet4Address)addr).getAddress(); + for (i=0;i<4;++i){ + addrbytes[i]=(byte) (addrbytes[i]&(reachabilityEntry.getMask())[i]); + } + return Arrays.equals(addrbytes,reachabilityEntry.getAggregatedIPRange().getAddress()); + } + + public ReachabilityEntry getReachabilityEntry() { + return reachabilityEntry; + } + + public LinkedList getInterDomainLinks() { + return interDomainLinks; + } + + @Override + public String printInterDomainLinks(){ + String topoString=""; + + int size = interDomainLinks.size(); + topoString="Interdomain Link list: \r\n"; + for (int i=0;i sourceVertexList, LinkedList targetVertexList, int wavelength, boolean bidirectional){ + TEDBlock.lock(); + try { + for (int i=0;i sourceVertexList, LinkedList targetVertexList, int wavelength, boolean bidirectional){ + // TODO Auto-generated method stub + //Delete the resource reservation + TEDBlock.lock(); + try { + for (int i=0;i graph= ted.getNetworkGraph(); + IntraDomainEdge edge=lowerLayerGraph.getEdge(sourceVertexList.get(i),targetVertexList.get(i) ); + edge.getTE_info().setWavelengthUnReserved(wavelength); + if (bidirectional == true) + { + edge=lowerLayerGraph.getEdge(targetVertexList.get(i), sourceVertexList.get(i)); + edge.getTE_info().setWavelengthUnReserved(wavelength); + } + } + }finally{ + TEDBlock.unlock(); + } + for (int i=0;i edgeSet= lowerLayerGraph.edgeSet(); + Iterator edgeIterator=edgeSet.iterator(); + while (edgeIterator.hasNext()){ + IntraDomainEdge edge= edgeIterator.next(); + edge.TE_info.setAllWavelengtshUnReserved(); + } + }finally{ + TEDBlock.unlock(); + } + for (int i=0;i sourceVertexList, + LinkedList targetVertexList, int wavelength, + boolean bidirectional, int m) { + // TODO Auto-generated method stub + } + + @Override + public void notifyWavelengthReservationSSON( + LinkedList sourceVertexList, + LinkedList targetVertexList, int wavelength, + boolean bidirectional, int m) { + // TODO Auto-generated method stub + } + + @Override + public SSONInformation getSSONinfo() { + // TODO Auto-generated method stub + return null; + } + + + @Override + public Set getIntraDomainLinks() { + // TODO Auto-generated method stub + return null; + } + + + @Override + public void notifyWavelengthReservationWLAN( + LinkedList sourceVertexList, + LinkedList targetVertexList, + LinkedList wlans, boolean bidirectional) { + // TODO Auto-generated method stub + + } + + + @Override + public void registerSSON(SSONListener compAlgPreComp) { + // TODO Auto-generated method stub + + } + + + @Override + public Inet4Address getDomainID() { + // TODO Auto-generated method stub + return null; + } + + + @Override + public void setWSONinfo(WSONInformation wSONinfo) { + // TODO Auto-generated method stub + + } + + + @Override + public void setSSONinfo(SSONInformation sSONinfo) { + // TODO Auto-generated method stub + + } + + + @Override + public void createGraph() { + // TODO Auto-generated method stub + + } + + + @Override + public Set getIntraDomainLinksvertexSet() { + // TODO Auto-generated method stub + return null; + } + + + @Override + public Hashtable getNodeTable() { + // TODO Auto-generated method stub + return null; + } + + + @Override + public IT_Resources getItResources() { + // TODO Auto-generated method stub + return null; + } + + + @Override + public void setItResources(IT_Resources itResources) { + // TODO Auto-generated method stub + + } +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/Node_Info.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/Node_Info.java new file mode 100644 index 000000000..bc523ba5a --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/Node_Info.java @@ -0,0 +1,207 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb; + +import java.net.Inet4Address; +import java.util.LinkedList; + +import es.tid.of.DataPathID; + +public class Node_Info { + + //we specify we we learn the topology from + + private String learntFrom = null; + // for the moment only ospf-non pseudo supported + private Inet4Address igp_ident = null; + + //caracterizacion + private Inet4Address as_number, area_id, bgpls_ident, ipv4AddressLocalNode= null; + private DataPathID dataPathIDLocalNode; + private boolean overload_bit = false; + private boolean attached_bit = false; + private boolean external_bit = false; + private boolean abr_bit = false; + private byte[] name; + private LinkedList ipv4areaIDs = new LinkedList (); + private int sid; + + + + + public Node_Info() { + // TODO Auto-generated constructor stub + } + + public Node_Info(Inet4Address ipv4Address_ospf, Inet4Address as_number, + boolean overload_bit, boolean attached_bit, boolean external_bit, + boolean abr_bit, byte[] name, LinkedList ipv4areaIDs, Inet4Address ipv4AdddressLN) { + super(); + this.igp_ident = ipv4Address_ospf; + this.as_number = as_number; + this.overload_bit = overload_bit; + this.attached_bit = attached_bit; + this.external_bit = external_bit; + this.abr_bit = abr_bit; + this.name = name; + this.ipv4areaIDs = ipv4areaIDs; + this.ipv4AddressLocalNode = ipv4AdddressLN; + } + + public LinkedList getIpv4areaIDs() { + return ipv4areaIDs; + } + + public void setIpv4areaIDs(LinkedList ipv4areaIDs) { + this.ipv4areaIDs = ipv4areaIDs; + } + + public byte[] getName() { + return name; + } + + + public void setName(byte[] name) { + this.name = name; + } + + public boolean isOverload_bit() { + return overload_bit; + } + + + public void setOverload_bit(boolean overload_bit) { + this.overload_bit = overload_bit; + } + + + public boolean isAttached_bit() { + return attached_bit; + } + + + public void setAttached_bit(boolean attached_bit) { + this.attached_bit = attached_bit; + } + + + public boolean isExternal_bit() { + return external_bit; + } + + + public void setExternal_bit(boolean external_bit) { + this.external_bit = external_bit; + } + + + public Inet4Address getArea_id() { + return area_id; + } + + public void setArea_id(Inet4Address area_id) { + this.area_id = area_id; + } + + public boolean isAbr_bit() { + return abr_bit; + } + + + public void setAbr_bit(boolean abr_bit) { + this.abr_bit = abr_bit; + } + + + public Inet4Address getIpv4Address() { + return igp_ident; + } + + + public void setIpv4Address(Inet4Address ipv4Address_ospf) { + this.igp_ident = ipv4Address_ospf; + } + + + public Inet4Address getIpv4AddressLocalNode() { + return ipv4AddressLocalNode; + } + + public void setIpv4AddressLocalNode(Inet4Address ipv4AddressLocalNode) { + this.ipv4AddressLocalNode = ipv4AddressLocalNode; + } + + public DataPathID getDataPathLocalNode() { + return dataPathIDLocalNode; + } + + public void setDataPathLocalNode(DataPathID dataPathLocalNode) { + this.dataPathIDLocalNode = dataPathLocalNode; + } + + public Inet4Address getAs_number() { + return as_number; + } + + + public void setAs_number(Inet4Address as_number) { + this.as_number = as_number; + } + + public Inet4Address getBgpls_ident() { + return bgpls_ident; + } + + public void setBgpls_ident(Inet4Address bgpls_ident) { + this.bgpls_ident = bgpls_ident; + } + + public String getLearntFrom() { + return learntFrom; + } + + public void setLearntFrom(String learntFrom) { + this.learntFrom = learntFrom; + } + + public void setSID(int sid) { + this.sid = sid; + } + + public int getSid(){ + return sid; + } + public String toString(){ + String ret = ""; + + if(igp_ident!=null) + ret = ret + "IGP-ID:" + this.getIpv4Address() +"\t"; + if(as_number!=null) + ret = ret + "as_num:" + this.getAs_number() +"\t"; + if(bgpls_ident != null) + ret = ret + "BGPLS-ident:" + this.getBgpls_ident() +"\t"; + if(name != null) + ret = ret + "Name :" + this.getName() +"\t"; + if(ipv4AddressLocalNode!=null) + ret = ret +"Local Node IP Address: " + this.getIpv4AddressLocalNode() + "\t"; + if(sid!=0) + ret = ret + "SID:" + this.getSid() +"\t"; + + return ret; + + } + + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/ReachabilityEntry.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/ReachabilityEntry.java new file mode 100644 index 000000000..d51896c0e --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/ReachabilityEntry.java @@ -0,0 +1,85 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb; + +import java.net.Inet4Address; + +public class ReachabilityEntry { + + public Inet4Address domainId; + public byte[] mask; + public int prefix; + + //public byte[] aggregatedIPRange; + public Inet4Address aggregatedIPRange; + + public ReachabilityEntry(){ + mask = new byte[4]; + + } + public ReachabilityEntry(Inet4Address domainId){ + mask = new byte[4]; + + } + + public int getPrefix() { + return prefix; + } + + public Inet4Address getAggregatedIPRange() { + return aggregatedIPRange; + } + + public void setAggregatedIPRange(Inet4Address aggregatedIPRange) { + this.aggregatedIPRange = aggregatedIPRange; + } + + public byte[] getMask() { + return mask; + } + + + public Inet4Address getDomainId() { + return domainId; + } + + public void setDomainId(Inet4Address domainId) { + this.domainId = domainId; + } + + public void setMask(byte[] mask) { + this.mask = mask; + } + public void setPrefix(int prefix) { + this.prefix = prefix; + } + public String toString(){ + String ret=aggregatedIPRange.toString()+"\\"+prefix+" ("+domainId.toString()+")"; + return ret; + } + + @Override + public boolean equals(Object reachabilityObject) { + if ((domainId.equals(((ReachabilityEntry)reachabilityObject).getDomainId()))&& + (aggregatedIPRange.equals(((ReachabilityEntry)reachabilityObject).getAggregatedIPRange()))&& + (prefix == ((ReachabilityEntry)reachabilityObject).getPrefix())){ + return true; + } + + return false; + } + + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/ReachabilityManager.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/ReachabilityManager.java new file mode 100644 index 000000000..cf2f3c5c3 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/ReachabilityManager.java @@ -0,0 +1,162 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb; + +import java.net.Inet4Address; +import java.util.Iterator; +import java.util.LinkedList; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import es.tid.rsvp.objects.subobjects.EROSubobject; +import es.tid.rsvp.objects.subobjects.IPv4prefixEROSubobject; +import es.tid.rsvp.objects.subobjects.SubObjectValues; + +/** + * Class that maintains a table with Reachability entries. + * It has a method to add a reachability entry + * It has a method to query the domain of an IPv4 endpoint + * It has a method to query if an address begins to a given IP range + * KNOWN BUGS: + * * When a reachability entry is added, it is not checked if + * it is already there or not. + * * Reachability entries cannot be removed + * + * @author ogondio + * + */ +public class ReachabilityManager { + + /** + * Table with IP address/prefix --> domain + */ + LinkedList reachability; + /** + * The logger + */ + private Logger log; + + /** + * ReachabilityManager constructor + */ + public ReachabilityManager(){ + log=LoggerFactory.getLogger("PCEServer"); + reachability=new LinkedList(); + } + + /** + * gets the domain of an IPv4 EndpointAddress + * @param endpointAddress the address to query + * @return The domain id if the endpointAddress belongs to a domain, null otherwise. + */ + public Inet4Address getDomain(Inet4Address endpointAddress) { + //String domain="0.0.0.1"; + Iterator it=reachability.iterator(); + while (it.hasNext()){ + ReachabilityEntry ra=it.next(); + //log.info("reachability entry "+ra.aggregatedIPRange+" mask "+(ra.mask[0]&0xFF)+"."+(ra.mask[1]&0xFF)+"."+(ra.mask[2]&0xFF)+"."+(ra.mask[3]&0xFF)); + if (belongsToDomain(endpointAddress, ra.mask, ra.aggregatedIPRange)){ + return ra.domainId; + } + } + return null; + + } + + /** + * Method to determine if the address 'nodeAdrress' belongs to the aggregated IP address range given by the mask and the addresss 'aggregatedIPRange' + * @param nodeAddress The address to query + * @param mask The 32 bit network mask + * @param aggregatedIPRange The aggregated IP address + * @return true if it belongs to the range, false if it does not belong to the range + */ + public boolean belongsToDomain(Inet4Address nodeAddress, byte []mask, Inet4Address aggregatedIPRange){ + int i; + //byte [] networkAddress=new byte[4]; + byte [] bytesAggregatedIPRange=aggregatedIPRange.getAddress(); + byte [] bytesNodeAddress=nodeAddress.getAddress(); + boolean found=true; + for (i=0;i<4;++i){ + //networkAddress[i]= (byte) ((bytesNodeAddress[i]&mask[i])&0xFF) ; + //log.info("network Node Address[i]: "+(networkAddress[i]&0xFF)); + //log.info("bytesAggregatedIPRange["+i+"]: "+((bytesAggregatedIPRange[i]&mask[i])&0xFF)); + //log.info("bytesNodeAddress["+i+"]: "+((bytesNodeAddress[i]&mask[i])&0xFF)); + if ((byte)((bytesAggregatedIPRange[i]&mask[i])&0xFF)!=(byte)((bytesNodeAddress[i]&mask[i])&0xFF)){ + found=false; + return found; + } + } + return found; + } + + /** + * Adds a ERO Subobject associated with a given domainId to the reachability table + * @param domainId Domain ID + * @param eroso ERO Subobject + */ + public void addEROSubobject(Inet4Address domainId, EROSubobject eroso ){ + if (eroso.getType()==SubObjectValues.ERO_SUBOBJECT_IPV4PREFIX){ + log.info("Adding IPv4 ERO Subobject to the Reachability Database"); + IPv4prefixEROSubobject ipv4eroso=(IPv4prefixEROSubobject)eroso; + //long mask=(long)0xFFFFFFFF-(long)Math.pow(2, 32-ipv4eroso.getPrefix())-1; + log.info("prefix "+ipv4eroso.getPrefix()); + long resta=((long)0x1<>>24 & 0xFF); + mask[1]=(byte)(maskLong>>>16 & 0xFF); + mask[2]=(byte)(maskLong>>>8 & 0xFF); + mask[3]=(byte)(maskLong& 0xFF); + log.info("mask: "+(mask[0]&0xFF)+"."+(mask[1]&0xFF)+"."+(mask[2]&0xFF)+"."+(mask[3]&0xFF)); + log.info("Domain ID: "+domainId+" mask "+mask+" IPv4 Address: "+ipv4eroso.getIpv4address());//Pasar a FINE + addIPv4Entry(domainId,mask,ipv4eroso.getIpv4address(),ipv4eroso.getPrefix()); + } + + } + + private void addIPv4Entry(Inet4Address domainId,byte [] mask,Inet4Address aggregatedIPRange,int prefix){ + ReachabilityEntry ra=new ReachabilityEntry(); + ra.aggregatedIPRange=aggregatedIPRange; + ra.mask=mask; + ra.domainId=domainId; + ra.prefix=prefix; + if (!(reachability.contains(ra))){ + reachability.add(ra); + } + return; + } + + /** + * Print the reachability table + * @return String with the reachability information + */ + public String printReachability(){ + String reachabilityString; + Iterator reachabIterator=reachability.iterator(); + reachabilityString="Reachability entries: \r\n"; + while (reachabIterator.hasNext()){ + ReachabilityEntry entry= reachabIterator.next(); + reachabilityString=reachabilityString+"\t"+entry.toString()+"\r\n"; + } + + return reachabilityString; + } + + public LinkedList getReachability() { + return reachability; + } + + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SSONInformation.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SSONInformation.java new file mode 100644 index 000000000..ff69b8901 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SSONInformation.java @@ -0,0 +1,88 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb; + +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.AvailableLabels; + +/** + * Label information in the special case of a Switched Spectrum Optical Network based on Flexgrid. + * @author amll + * + */ + +public class SSONInformation { + /** + * In case the Network is SSON, this is the list of available Labels + */ + private AvailableLabels commonAvailableLabels; + + /** + * In case the Network is SSON, this is the number of wavelengths. -1 means it is not WSON. + */ + private int numLambdas=-1; + /** + * Spectral Grid of the optical network. + */ + public int grid=0; + /** + * Channel Spacing + */ + public int cs=0; + /** + * Minimum central frequency available in the spectral grid available to be assigned to a LSP. + */ + public int nMin=0; + + public int getGrid() { + return grid; + } + + public void setGrid(int grid) { + this.grid = grid; + } + + public int getCs() { + return cs; + } + + public void setCs(int cs) { + this.cs = cs; + } + + + public int getnMin() { + return nMin; + } + + public void setnMin(int nMin) { + this.nMin = nMin; + } + + public AvailableLabels getCommonAvailableLabels() { + return commonAvailableLabels; + } + + public void setCommonAvailableLabels(AvailableLabels commonAvailableLabels) { + this.commonAvailableLabels = commonAvailableLabels; + } + + public int getNumLambdas() { + return numLambdas; + } + + public void setNumLambdas(int numLambdas) { + this.numLambdas = numLambdas; + } +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SSONListener.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SSONListener.java new file mode 100644 index 000000000..ce769c41c --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SSONListener.java @@ -0,0 +1,28 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb; + +import java.util.LinkedList; + +public interface SSONListener extends TEDListener{ + + public void notifyWavelengthReservationSSON(LinkedList sourceVertexList, + LinkedList targetVertexList, int wavelength, int m); + + void notifyWavelengthEndReservationSSON( + LinkedList sourceVertexList, + LinkedList targetVertexList, int wavelength, int m); + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SimpleTEDB.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SimpleTEDB.java new file mode 100644 index 000000000..f2d5dbc89 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/SimpleTEDB.java @@ -0,0 +1,786 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb; + +import java.net.Inet4Address; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Set; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.jgrapht.graph.SimpleDirectedWeightedGraph; + +import es.tid.of.DataPathID; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.complexFields.BitmapLabelSet; + +/** + * Traffic Engineering Database of a Domain. + * + * + * @author ogondio, mcs, b.mvas + * + */ +public class SimpleTEDB implements DomainTEDB{ + + private Inet4Address domainID; + + private IT_Resources itResources; + + /** + * List of algorithms that will be notified when there are significant changes in the TED + */ + private ArrayList registeredAlgorithms; + /** + * List of algorithms SSON that will be notified when there are significant changes in the TED + */ + private ArrayList registeredAlgorithmssson; + /** + * Graph of the Network + */ + private SimpleDirectedWeightedGraph networkGraph; + + /** + * List of interdomain Links + */ + private LinkedList interDomainLinks = new LinkedList(); + + /* + * List of Intradomain Edges + * Please, It's not the same as intraDomainLinks + * This has been created to support multiedges between two nodes + */ + private LinkedList intraDomainEdges = new LinkedList(); + + + /** + * Reachability information + */ + private ReachabilityEntry reachabilityEntry; + /** + * Information about the labels in a WSON network. + */ + private WSONInformation WSONinfo=null; + /** + * Information about the labels in a SSON network. + */ + private SSONInformation SSONinfo=null; + + private Lock TEDBlock; + + private Hashtable NodeTable; + + private boolean multidomain=false;//By default, the TED has only one domain + Logger log; + public SimpleTEDB(){ + log=LoggerFactory.getLogger("TEDBParser"); + registeredAlgorithms= new ArrayList(); + registeredAlgorithmssson= new ArrayList(); + TEDBlock=new ReentrantLock(); + NodeTable = new Hashtable(); + } + + public SimpleDirectedWeightedGraph getDuplicatedNetworkGraph(){ + SimpleDirectedWeightedGraph graphCopy; + TEDBlock.lock(); + try{ + graphCopy= (SimpleDirectedWeightedGraph) networkGraph.clone(); + } finally{ + TEDBlock.unlock(); + } + return graphCopy; + } + public void createGraph(){ + networkGraph = new SimpleDirectedWeightedGraph(IntraDomainEdge.class); + reachabilityEntry = new ReachabilityEntry(); + } + + public void initializeFromFile(String file){ + initializeFromFile(file, null, false,0,Integer.MAX_VALUE, false,false); + } + public void initializeFromFile(String file, String layer){ + initializeFromFile(file, layer, false,0,Integer.MAX_VALUE, false,false); + } + public void initializeFromFile(String file, String layer, boolean multidomain){ + initializeFromFile(file, layer, multidomain,0,Integer.MAX_VALUE, false,false); + } + public void initializeFromFile(String file, String layer, boolean multidomain, boolean isSSON){ + initializeFromFile(file, layer, multidomain,0,Integer.MAX_VALUE, isSSON,false); + } + public void initializeFromFile(String file, String layer, boolean multidomain,int lambdaIni, int lambdaEnd){ + initializeFromFile(file, layer, multidomain,0,Integer.MAX_VALUE, false,false); + } + public void initializeFromFile(String file, String layer, boolean multidomain, int lambdaIni, int lambdaEnd, boolean isSSON,boolean readOnlyInterDomainLinks){ + initializeFromFile( file, layer, multidomain, lambdaIni, lambdaEnd, isSSON, readOnlyInterDomainLinks, false); + } + + public void initializeFromFile(String file, String layer, boolean multidomain, int lambdaIni, int lambdaEnd, boolean isSSON,boolean readOnlyInterDomainLinks, boolean isWLAN){ + domainID=FileTEDBUpdater.getDomainIDfromSimpleDomain(file); + if (readOnlyInterDomainLinks){ + log.info("Read Only Inter Domain Links"); + networkGraph = new SimpleDirectedWeightedGraph(IntraDomainEdge.class); + if (!multidomain){ + interDomainLinks = FileTEDBUpdater.readInterDomainLinks(file); + } + reachabilityEntry = new ReachabilityEntry(); + if (!multidomain){ + FileTEDBUpdater.getDomainReachabilityFromFile(file,reachabilityEntry); + } + if((isSSON==true)&(!isWLAN)){ + SSONinfo = FileTEDBUpdater.getSSONInformation(file); + }else if (isWLAN) + { + + } + else + { + WSONinfo = FileTEDBUpdater.getWSONInformation(file); + } + }else{ + if((isSSON==true)&&(!isWLAN)){ + networkGraph=FileTEDBUpdater.readNetwork(file,layer, multidomain,lambdaIni,lambdaEnd, isSSON); + SSONinfo = FileTEDBUpdater.getSSONInformation(file); + } + else if (isWLAN) + { + networkGraph=FileTEDBUpdater.readNetwork(file,layer, multidomain,lambdaIni,lambdaEnd, isSSON); + } + else{ + networkGraph=FileTEDBUpdater.readNetwork(file,layer, multidomain,lambdaIni,lambdaEnd); + WSONinfo = FileTEDBUpdater.getWSONInformation(file); + } + // if (lambdaEnd!=Integer.MAX_VALUE){ + // notifyAlgorithms( lambdaIni, lambdaEnd); + // } + Iterator itervertex=networkGraph.vertexSet().iterator(); + + /** Se podrian sacar a una funcion externa ambos 'while' + * Rellenar info table + * Rellenar info edge + * Preguntar a Oscar + */ + while (itervertex.hasNext()) { + Object address = itervertex.next(); + Node_Info ni = new Node_Info(); + if (address instanceof Inet4Address){ + ni.setIpv4AddressLocalNode((Inet4Address)address); + ni.setIpv4Address((Inet4Address)address);//de momento asumimos que aprendemos ospf + } else if (address instanceof DataPathID) { + ni.setDataPathLocalNode((DataPathID)address); + } + ni.setLearntFrom("Fom XML"); + ni.setAs_number(domainID); + NodeTable.put(address, ni); + } + + Iterator iteredge=networkGraph.edgeSet().iterator(); + while (iteredge.hasNext()) { + IntraDomainEdge id = (IntraDomainEdge) iteredge.next(); + try{ + Inet4Address ipSource = (Inet4Address) (id.getSource()); + Inet4Address ipDest = (Inet4Address) (id.getTarget()); + id.setLearntFrom("From XML"); + Node_Info origin = new Node_Info(); + Node_Info destination = new Node_Info(); + origin.setIpv4AddressLocalNode(ipSource); + origin.setAs_number(domainID); + origin.setLearntFrom("FromXML"); + destination.setIpv4AddressLocalNode(ipDest); + destination.setAs_number(domainID); + destination.setLearntFrom("FromXML"); + id.setLocal_Node_Info(origin); + id.setRemote_Node_Info(destination); + NodeTable.get(ipSource).setSID(id.getSrc_sid()); + NodeTable.get(ipDest).setSID(id.getDst_sid()); + }catch (Exception e1){ + DataPathID dpSource = (DataPathID) (id.getSource()); + DataPathID dpDest = (DataPathID) (id.getTarget()); + id.setLearntFrom("From XML"); + Node_Info origin = new Node_Info(); + Node_Info destination = new Node_Info(); + origin.setDataPathLocalNode(dpSource); + origin.setAs_number(domainID); + origin.setLearntFrom("FromXML"); + destination.setDataPathLocalNode(dpDest); + destination.setAs_number(domainID); + destination.setLearntFrom("FromXML"); + id.setLocal_Node_Info(origin); + id.setRemote_Node_Info(destination); + //NodeTableDataPath.get(dpSource).setSID(id.getSrc_sid()); + //NodeTableDataPath.get(dpDest).setSID(id.getDst_sid()); + } + + } + } + + + if (!multidomain){ + interDomainLinks = FileTEDBUpdater.readInterDomainLinks(file); + } + else { + interDomainLinks = new LinkedList(); + } + reachabilityEntry = new ReachabilityEntry(); + if (!multidomain){ + FileTEDBUpdater.getDomainReachabilityFromFile(file,reachabilityEntry); + } + + Iterator edgeIt = interDomainLinks.iterator(); + while (edgeIt.hasNext()) { + InterDomainEdge id = (InterDomainEdge) edgeIt.next(); + try { + Inet4Address ipSource = (Inet4Address) (id.src_router_id); + Inet4Address ipDest = (Inet4Address) (id.dst_router_id); + id.setLearntFrom("From XML"); + Node_Info origin = new Node_Info(); + Node_Info destination = new Node_Info(); + origin.setIpv4AddressLocalNode(ipSource); + origin.setAs_number(domainID); + origin.setLearntFrom("FromXML"); + destination.setIpv4AddressLocalNode(ipDest); + destination.setAs_number((Inet4Address) id.domain_dst_router); + destination.setLearntFrom("FromXML"); + id.setLocal_Node_Info(origin); + id.setRemote_Node_Info(destination); + } catch (Exception e) { + DataPathID dpSource = (DataPathID) (id.src_router_id); + DataPathID dpDest = (DataPathID) (id.dst_router_id); + id.setLearntFrom("From XML"); + Node_Info origin = new Node_Info(); + Node_Info destination = new Node_Info(); + origin.setDataPathLocalNode(dpSource); + origin.setAs_number(domainID); + origin.setLearntFrom("FromXML"); + destination.setDataPathLocalNode(dpDest); + destination.setAs_number((Inet4Address) id.domain_dst_router); + destination.setLearntFrom("FromXML"); + id.setLocal_Node_Info(origin); + id.setRemote_Node_Info(destination); + } + } + + } + + public void notifyAlgorithms( int lambdaIni,int lambdaEnd){ + LinkedList ipListScr = new LinkedList (); + LinkedList ipListDst = new LinkedList (); + Set it =this.networkGraph.edgeSet(); + int numLabels=0; + for (IntraDomainEdge edge:it){ + numLabels=edge.TE_info.getAvailableLabels().getLabelSet().getNumLabels(); + for (int i=0;i getIntraDomainEdges() { + return intraDomainEdges; + } + + public void setIntraDomainEdges(LinkedList intraDomainEdges) { + this.intraDomainEdges = intraDomainEdges; + } + + public ReachabilityEntry getReachabilityEntry() { + return reachabilityEntry; + } + + public void setReachabilityEntry(ReachabilityEntry reachabilityEntry) { + this.reachabilityEntry = reachabilityEntry; + } + + public SimpleDirectedWeightedGraph getNetworkGraph() { + return networkGraph; + } + + public void setNetworkGraph( + SimpleDirectedWeightedGraph networkGraph) { + this.networkGraph = networkGraph; + } + + public LinkedList getInterDomainLinks() { + return interDomainLinks; + } + public void setInterDomainLinks(LinkedList interDomainLinks) { + this.interDomainLinks = interDomainLinks; + } + + /** + * Return true if scr and dst are linked by an InterDomainLink + * @param src Source + * @param dst Destination + * @return true if scr and dst are linked by an InterDomainLink + */ + public InterDomainEdge getInterdomainLink(Object src, Object dst){ + + int size = interDomainLinks.size(); + InterDomainEdge edge= new InterDomainEdge(src,dst); + for (int i=0;i vetexSet= networkGraph.vertexSet(); + Iterator vertexIterator=vetexSet.iterator(); + topoString="Nodes: \r\n"; + while (vertexIterator.hasNext()){ + Object vertex= vertexIterator.next(); + topoString=topoString+"\t"+vertex.toString()+"\r\n"; + } + topoString=topoString+"Node Information Table::: \r\n"+NodeTable.toString()+"\r\n"; + Set edgeSet= networkGraph.edgeSet(); + if (edgeSet != null){ + Iterator edgeIterator=edgeSet.iterator(); + topoString=topoString+"Intradomain Link list: \r\n"; + while (edgeIterator.hasNext()){ + IntraDomainEdge edge= edgeIterator.next(); + topoString=topoString+"\t"+edge.toString()+"\n"; + } + } + if (interDomainLinks != null) + topoString=topoString+printInterDomainLinks(); + return topoString; + } + + public String printInterDomainLinks(){ + String topoString=""; + + int size = interDomainLinks.size(); + log.info("Size of InterDomainLinks: "+size); + topoString="Interdomain Link list: \r\n"; + for (int i=0;i sourceVertexList,LinkedList targetVertexList,LinkedList wlans, boolean bidirectional) + { + TEDBlock.lock(); + try { + for (int i=0;i sourceVertexList, LinkedList targetVertexList, int wavelength, boolean bidirectional){ + TEDBlock.lock(); + try { + for (int i=0;i sourceVertexList, LinkedList targetVertexList, int wavelength, boolean bidirectional, int m){ + TEDBlock.lock(); + try { + for (int j=0;j<2*m;j++){ + for (int i=0;i sourceVertexList, LinkedList targetVertexList, int wavelength, boolean bidirectional, int m){ + // TODO Auto-generated method stub + //Delete the resource reservation + TEDBlock.lock(); + try { + for (int j=0;j<2*m;j++){ + for (int i=0;i graph= ted.getNetworkGraph(); + IntraDomainEdge edge=networkGraph.getEdge(sourceVertexList.get(i),targetVertexList.get(i) ); + edge.getTE_info().setWavelengthUnReserved(wavelength-m+j); + //log.info("Derreserving in TEDB: "+edge.toString()); + if (bidirectional == true) + { + edge=networkGraph.getEdge(targetVertexList.get(i), sourceVertexList.get(i)); + edge.getTE_info().setWavelengthUnReserved(wavelength-m+j); + //log.info("Derreserving in TEDB: "+edge.toString()); + } + } + } + }finally{ + TEDBlock.unlock(); + } + for (int i=0;i sourceVertexList, LinkedList targetVertexList, int wavelength, boolean bidirectional){ + // TODO Auto-generated method stub + //Delete the resource reservation + TEDBlock.lock(); + try { + for (int i=0;i graph= ted.getNetworkGraph(); + IntraDomainEdge edge=networkGraph.getEdge(sourceVertexList.get(i),targetVertexList.get(i) ); + edge.getTE_info().setWavelengthUnReserved(wavelength); + //log.info(""+edge.toString()); + if (bidirectional == true) + { + edge=networkGraph.getEdge(targetVertexList.get(i), sourceVertexList.get(i)); + edge.getTE_info().setWavelengthUnReserved(wavelength); + //log.info(""+edge.toString()); + } + } + }finally{ + TEDBlock.unlock(); + } + for (int i=0;i getNodeTable() { + return NodeTable; + } + + public void setNodeTable(Hashtable nodeTable) { + NodeTable = nodeTable; + } + + public boolean isMultidomain() { + return multidomain; + } + + public void setMultidomain(boolean multidomain) { + this.multidomain = multidomain; + } + + public void registerSSON (SSONListener algo){ + registeredAlgorithmssson.add(algo); + } + + public void register (TEDListener algo){ + registeredAlgorithms.add(algo); + } + + @Override + public void notifyWavelengthChange(Object localInterfaceIPAddress, Object remoteInterfaceIPAddress, BitmapLabelSet previousBitmapLabelSet, BitmapLabelSet newBitmapLabelSet) { + for (int i=0;i edgeSet= networkGraph.edgeSet(); + Iterator edgeIterator=edgeSet.iterator(); + while (edgeIterator.hasNext()){ + IntraDomainEdge edge= edgeIterator.next(); + edge.TE_info.setAllWavelengtshUnReserved(); + } + }finally{ + TEDBlock.unlock(); + } + for (int i=0;i vetexSet= networkGraph.vertexSet(); + Iterator vertexIterator=vetexSet.iterator(); + topoString="NodesFEO: \r\n"; + while (vertexIterator.hasNext()){ + Object vertex= vertexIterator.next(); + topoString=topoString+"\t"+vertex.toString()+"\r\n"; + } + topoString=topoString+"Intradomain Link list: \r\n"; + Set edgeSet= networkGraph.edgeSet(); + Iterator edgeIterator=edgeSet.iterator(); + while (edgeIterator.hasNext()){ + IntraDomainEdge edge= edgeIterator.next(); + topoString=topoString+"\t"+edge.toString()+"\r\n"; + } + return topoString; + } + + @Override + public Inet4Address getDomainID() { + // TODO Auto-generated method stub + return domainID; + } + + public void setDomainID(Inet4Address domainID) { + this.domainID = domainID; + } + + @Override + public Set getIntraDomainLinks() { + return this.getNetworkGraph().edgeSet(); + } + + public Set getIntraDomainLinksvertexSet() { + return this.getNetworkGraph().vertexSet(); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((domainID == null) ? 0 : domainID.hashCode()); + result = prime * result + ((intraDomainEdges == null) ? 0 : intraDomainEdges.hashCode()); + result = prime * result + ((networkGraph == null) ? 0 : networkGraph.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; + SimpleTEDB other = (SimpleTEDB) obj; + if (intraDomainEdges == null) { + if (other.intraDomainEdges != null) + return false; + } else if (!intraDomainEdges.equals(other.intraDomainEdges)) + return false; + if (networkGraph == null) { + if (other.networkGraph != null) + return false; + } + for(Object v : networkGraph.vertexSet()){ + if(!other.networkGraph.containsVertex(v)) + return false; + } + + for(IntraDomainEdge e :networkGraph.edgeSet()){ + boolean flagEqual=false; + for(IntraDomainEdge otherE : other.networkGraph.edgeSet()){ + if(e.toString().equals(otherE.toString()))flagEqual=true; + } + if(flagEqual==false)return false; //edge not present in other + } + for(IntraDomainEdge e :other.networkGraph.edgeSet()){ + boolean flagEqual=false; + for(IntraDomainEdge otherE : networkGraph.edgeSet()){ + if(e.toString().equals(otherE.toString()))flagEqual=true; + } + if(flagEqual==false)return false; //edge not present in other + } + return true; + } + + public IT_Resources getItResources() { + return itResources; + } + + public void setItResources(IT_Resources itResources) { + this.itResources = itResources; + } + + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDB.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDB.java new file mode 100644 index 000000000..51fc3d8c1 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDB.java @@ -0,0 +1,37 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb; + +import java.util.LinkedList; + +/** + * Base Interface for a Generic Traffic Engineering Database + * @author ogondio + * + */ +public interface TEDB { + + public void initializeFromFile(String file); + + public void initializeFromFile(String file, String learnFrom); + + + public boolean isITtedb(); //FIXME: Remove! + + public String printTopology(); + + public LinkedList getInterDomainLinks(); + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDBUpdater.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDBUpdater.java new file mode 100644 index 000000000..fe261b80e --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDBUpdater.java @@ -0,0 +1,19 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb; + +public class TEDBUpdater { + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDListener.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDListener.java new file mode 100644 index 000000000..86e653ed0 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TEDListener.java @@ -0,0 +1,41 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb; + +import java.util.LinkedList; + +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.complexFields.BitmapLabelSet; + +public interface TEDListener { + + public void notifyNewVertex(Object vertex); + + public void notifyNewEdge(Object source, Object destination); + + public void notifyWavelengthStatusChange(Object source, Object destination, BitmapLabelSet previousBitmapLabelSet, BitmapLabelSet newBitmapLabelSet); + + public void notifyWavelengthReservation(LinkedList sourceVertexList, LinkedList targetVertexList, int wavelength); + + public void notifyWavelengthEndReservation(LinkedList sourceVertexList, LinkedList targetVertexList, int wavelength); + + public void notifyTEDBFullUpdate(); + + public void notifyNewEdgeIP(Object source, Object destination, TE_Information informationTEDB); + + public void notificationEdgeIP_AuxGraph(Object src, Object dst, TE_Information informationTEDB); + + public void notificationEdgeOPTICAL_AuxGraph(Object src, Object dst, int lambda); + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TE_Information.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TE_Information.java new file mode 100644 index 000000000..0e5476dfe --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/TE_Information.java @@ -0,0 +1,679 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb; + +import es.tid.bgp.bgp4.update.tlv.linkstate_attribute_tlvs.DefaultTEMetricLinkAttribTLV; +import es.tid.bgp.bgp4.update.tlv.linkstate_attribute_tlvs.IPv4RouterIDLocalNodeLinkAttribTLV; +import es.tid.bgp.bgp4.update.tlv.linkstate_attribute_tlvs.IPv4RouterIDRemoteNodeLinkAttribTLV; +import es.tid.bgp.bgp4.update.tlv.linkstate_attribute_tlvs.LinkProtectionTypeLinkAttribTLV; +import es.tid.bgp.bgp4.update.tlv.linkstate_attribute_tlvs.MF_OTPAttribTLV; +import es.tid.bgp.bgp4.update.tlv.linkstate_attribute_tlvs.MetricLinkAttribTLV; +import es.tid.bgp.bgp4.update.tlv.linkstate_attribute_tlvs.TransceiverClassAndAppAttribTLV; +import es.tid.bgp.bgp4.update.tlv.node_link_prefix_descriptor_subTLVs.MinMaxUndirectionalLinkDelayDescriptorSubTLV; +import es.tid.bgp.bgp4.update.tlv.node_link_prefix_descriptor_subTLVs.UndirectionalAvailableBandwidthDescriptorSubTLV; +import es.tid.bgp.bgp4.update.tlv.node_link_prefix_descriptor_subTLVs.UndirectionalDelayVariationDescriptorSubTLV; +import es.tid.bgp.bgp4.update.tlv.node_link_prefix_descriptor_subTLVs.UndirectionalLinkDelayDescriptorSubTLV; +import es.tid.bgp.bgp4.update.tlv.node_link_prefix_descriptor_subTLVs.UndirectionalLinkLossDescriptorSubTLV; +import es.tid.bgp.bgp4.update.tlv.node_link_prefix_descriptor_subTLVs.UndirectionalResidualBandwidthDescriptorSubTLV; +import es.tid.bgp.bgp4.update.tlv.node_link_prefix_descriptor_subTLVs.UndirectionalUtilizedBandwidthDescriptorSubTLV; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.AdministrativeGroup; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.AvailableLabels; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.IPv4RemoteASBRID; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.InterfaceSwitchingCapabilityDescriptor; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.LinkLocalRemoteIdentifiers; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.LinkProtectionType; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.MaximumBandwidth; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.MaximumReservableBandwidth; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.RemoteASNumber; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.SharedRiskLinkGroup; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.TrafficEngineeringMetric; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.UnreservedBandwidth; +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.complexFields.BitmapLabelSet; +import es.tid.rsvp.constructs.gmpls.DWDMWavelengthLabel; + +public class TE_Information { + + private TrafficEngineeringMetric trafficEngineeringMetric; + + private DefaultTEMetricLinkAttribTLV defaultTEMetric; + + private MaximumBandwidth maximumBandwidth; + + private MaximumReservableBandwidth maximumReservableBandwidth; + + private UnreservedBandwidth unreservedBandwidth; + + private AdministrativeGroup administrativeGroup; + + private LinkLocalRemoteIdentifiers linkLocalRemoteIdentifiers; + + private LinkProtectionType linkProtectionType; + + private LinkProtectionTypeLinkAttribTLV linkProtectionBGPLS; + + private InterfaceSwitchingCapabilityDescriptor interfaceSwitchingCapabilityDescriptor; + + private SharedRiskLinkGroup sharedRiskLinkGroup; + + private RemoteASNumber remoteASNumber; + + private IPv4RemoteASBRID iPv4RemoteASBRID; + + private IPv4RouterIDLocalNodeLinkAttribTLV iPv4LocalNode; + + private IPv4RouterIDRemoteNodeLinkAttribTLV iPv4RemoteNode; + + + private UndirectionalLinkDelayDescriptorSubTLV undirLinkDelay; + private MinMaxUndirectionalLinkDelayDescriptorSubTLV minMaxUndirLinkDelay; + private UndirectionalDelayVariationDescriptorSubTLV undirDelayVar; + private UndirectionalLinkLossDescriptorSubTLV undirLinkLoss; + private UndirectionalResidualBandwidthDescriptorSubTLV undirResidualBw; + private UndirectionalAvailableBandwidthDescriptorSubTLV undirAvailableBw; + private UndirectionalUtilizedBandwidthDescriptorSubTLV undirUtilizedBw; + + + private MetricLinkAttribTLV metric; + + private AvailableLabels availableLabels; + + private MF_OTPAttribTLV mfOTF; + + private TransceiverClassAndAppAttribTLV trans; + + private int NumberWLANs = 15; + + private boolean withWLANs = false; + + private boolean[] occupiedWLANs; + private boolean[] reservedWLANs; + + private boolean vlanLink = false; + + private int vlan; + + /** + * TEDB logger + */ + public TE_Information() + { + //initWLANs(); + } + + public AvailableLabels getAvailableLabels() { + return availableLabels; + } + + public void setAvailableLabels(AvailableLabels availableLabels) { + this.availableLabels = availableLabels; + } + + public TrafficEngineeringMetric getTrafficEngineeringMetric() { + return trafficEngineeringMetric; + } + + public void setTrafficEngineeringMetric( + TrafficEngineeringMetric trafficEngineeringMetric) { + this.trafficEngineeringMetric = trafficEngineeringMetric; + } + + public MaximumBandwidth getMaximumBandwidth() { + return maximumBandwidth; + } + + public void setMaximumBandwidth(MaximumBandwidth maximumBandwidth) { + this.maximumBandwidth = maximumBandwidth; + } + + public MaximumReservableBandwidth getMaximumReservableBandwidth() { + return maximumReservableBandwidth; + } + + public IPv4RouterIDRemoteNodeLinkAttribTLV getiPv4RemoteNode() { + return iPv4RemoteNode; + } + + public void setiPv4RemoteNode(IPv4RouterIDRemoteNodeLinkAttribTLV iPv4RemoteNode) { + this.iPv4RemoteNode = iPv4RemoteNode; + } + + public void setMaximumReservableBandwidth( + MaximumReservableBandwidth maximumReservableBandwidth) { + this.maximumReservableBandwidth = maximumReservableBandwidth; + } + + public UnreservedBandwidth getUnreservedBandwidth() { + return unreservedBandwidth; + } + + public void setUnreservedBandwidth(UnreservedBandwidth unreservedBandwidth) { + this.unreservedBandwidth = unreservedBandwidth; + } + + public UndirectionalLinkDelayDescriptorSubTLV getUndirLinkDelay() { + return undirLinkDelay; + } + + public void setUndirLinkDelay(UndirectionalLinkDelayDescriptorSubTLV undirLinkDelay) { + this.undirLinkDelay = undirLinkDelay; + } + + public MinMaxUndirectionalLinkDelayDescriptorSubTLV getMinMaxUndirLinkDelay() { + return minMaxUndirLinkDelay; + } + + public void setMinMaxUndirLinkDelay(MinMaxUndirectionalLinkDelayDescriptorSubTLV minMaxUndirLinkDelay) { + this.minMaxUndirLinkDelay = minMaxUndirLinkDelay; + } + + public UndirectionalDelayVariationDescriptorSubTLV getUndirDelayVar() { + return undirDelayVar; + } + + public void setUndirDelayVar(UndirectionalDelayVariationDescriptorSubTLV undirDelayVar) { + this.undirDelayVar = undirDelayVar; + } + + public UndirectionalLinkLossDescriptorSubTLV getUndirLinkLoss() { + return undirLinkLoss; + } + + public void setUndirLinkLoss(UndirectionalLinkLossDescriptorSubTLV undirLinkLoss) { + this.undirLinkLoss = undirLinkLoss; + } + + public UndirectionalResidualBandwidthDescriptorSubTLV getUndirResidualBw() { + return undirResidualBw; + } + + public void setUndirResidualBw(UndirectionalResidualBandwidthDescriptorSubTLV undirResidualBw) { + this.undirResidualBw = undirResidualBw; + } + + public UndirectionalAvailableBandwidthDescriptorSubTLV getUndirAvailableBw() { + return undirAvailableBw; + } + + public void setUndirAvailableBw(UndirectionalAvailableBandwidthDescriptorSubTLV undirAvailableBw) { + this.undirAvailableBw = undirAvailableBw; + } + + public UndirectionalUtilizedBandwidthDescriptorSubTLV getUndirUtilizedBw() { + return undirUtilizedBw; + } + + public void setUndirUtilizedBw(UndirectionalUtilizedBandwidthDescriptorSubTLV undirUtilizedBw) { + this.undirUtilizedBw = undirUtilizedBw; + } + + public AdministrativeGroup getAdministrativeGroup() { + return administrativeGroup; + } + + public void setAdministrativeGroup(AdministrativeGroup administrativeGroup) { + this.administrativeGroup = administrativeGroup; + } + + public LinkLocalRemoteIdentifiers getLinkLocalRemoteIdentifiers() { + return linkLocalRemoteIdentifiers; + } + + public void setLinkLocalRemoteIdentifiers( + LinkLocalRemoteIdentifiers linkLocalRemoteIdentifiers) { + this.linkLocalRemoteIdentifiers = linkLocalRemoteIdentifiers; + } + + public LinkProtectionType getLinkProtectionType() { + return linkProtectionType; + } + + public void setLinkProtectionType(LinkProtectionType linkProtectionType) { + this.linkProtectionType = linkProtectionType; + } + + public InterfaceSwitchingCapabilityDescriptor getInterfaceSwitchingCapabilityDescriptor() { + return interfaceSwitchingCapabilityDescriptor; + } + + public void setInterfaceSwitchingCapabilityDescriptor( + InterfaceSwitchingCapabilityDescriptor interfaceSwitchingCapabilityDescriptor) { + this.interfaceSwitchingCapabilityDescriptor = interfaceSwitchingCapabilityDescriptor; + } + + public SharedRiskLinkGroup getSharedRiskLinkGroup() { + return sharedRiskLinkGroup; + } + + public void setSharedRiskLinkGroup(SharedRiskLinkGroup sharedRiskLinkGroup) { + this.sharedRiskLinkGroup = sharedRiskLinkGroup; + } + + public RemoteASNumber getRemoteASNumber() { + return remoteASNumber; + } + + public void setRemoteASNumber(RemoteASNumber remoteASNumber) { + this.remoteASNumber = remoteASNumber; + } + + public IPv4RemoteASBRID getiPv4RemoteASBRID() { + return iPv4RemoteASBRID; + } + + public void setiPv4RemoteASBRID(IPv4RemoteASBRID iPv4RemoteASBRID) { + this.iPv4RemoteASBRID = iPv4RemoteASBRID; + } + + public int getNumberWLANs() { + return NumberWLANs; + } + + public void setNumberWLANs(int numberWLANs) { + NumberWLANs = numberWLANs; + } + + public boolean isWLANFree() + { + /* + for (int i = 0; i < reservedWLANs.length; i++) + { + if (reservedWLANs[i] == false) + { + return true; + } + } + return false; + */ + return true; + } + + public Integer getFreeWLAN() + { + for (int i = 0; i < reservedWLANs.length; i++) + { + if (reservedWLANs[i] == false) + { + return i; + } + } + return null; + } + + public void initWLANs() + { + withWLANs = true; + occupiedWLANs = new boolean[NumberWLANs]; + reservedWLANs = new boolean[NumberWLANs]; + for (int i = 0 ; i < NumberWLANs ; i++) + { + occupiedWLANs[i] = false; + reservedWLANs[i] = false; + } + } + + public void createBitmapLabelSet(int numLabels,int grid, int cs,int n){ + + createBitmapLabelSet(numLabels,grid,cs,n,0,numLabels); + } + public void createBitmapLabelSet(int numLabels,int grid, int cs,int n,int lambdaIni, int lambdaEnd){ + //FIXME: no hay problema de que se salga el ancho de banda + //log.info("Creamos bit map"); + BitmapLabelSet bitmapLabelSet = new BitmapLabelSet(); + DWDMWavelengthLabel dwdmWavelengthLabel = new DWDMWavelengthLabel(); + dwdmWavelengthLabel.setGrid(grid); + dwdmWavelengthLabel.setChannelSpacing(cs); + dwdmWavelengthLabel.setN(n); + bitmapLabelSet.setDwdmWavelengthLabel(dwdmWavelengthLabel); + + int numberBytes = getNumberBytes(numLabels); + + byte[] bytesBitMap = new byte[numberBytes]; + for (int i=0;i>>(num_wavelength%8))); + } + } + public void setWavelengthFree(int num_wavelength) + { + if (withWLANs) + { + occupiedWLANs[num_wavelength] = false; + reservedWLANs[num_wavelength] = false; + } + else + { + int num_byte=num_wavelength/8; + ((BitmapLabelSet)this.getAvailableLabels().getLabelSet()).getBytesBitMap()[num_byte]=(byte)(((BitmapLabelSet)this.getAvailableLabels().getLabelSet()).getBytesBitMap()[num_byte]&(0xFFFF7F>>>(num_wavelength%8))); + } + } + + public void setWavelengthReserved(int num_wavelength){ + if (withWLANs) + { + reservedWLANs[num_wavelength] = true; + } + else + { + int num_byte=num_wavelength/8; +// if ( this.getAvailableLabels()==null){ +// PCEServer.log.info("AvailableLabels ES NULL"); +// +// } +// if ( this.getAvailableLabels().getLabelSet()==null){ +// PCEServer.log.info("AvailableLabels LABEL SET ES NULL"); +// +// } +// if (((BitmapLabelSet)this.getAvailableLabels().getLabelSet()).getBytesBitmapReserved()==null){ +// PCEServer.log.info("BytesBitmapReserved ES NULL"); +// +// } + + ((BitmapLabelSet)this.getAvailableLabels().getLabelSet()).getBytesBitmapReserved()[num_byte]=(byte)((((BitmapLabelSet)this.getAvailableLabels().getLabelSet()).getBytesBitmapReserved()[num_byte])|(0x80>>>(num_wavelength%8))); + } + } + + public void setWavelengthUnReserved(int num_wavelength){ + if (withWLANs) + { + reservedWLANs[num_wavelength] = false; + } + else + { + int num_byte=num_wavelength/8; + ((BitmapLabelSet)this.getAvailableLabels().getLabelSet()).getBytesBitmapReserved()[num_byte]=(byte)(((BitmapLabelSet)this.getAvailableLabels().getLabelSet()).getBytesBitmapReserved()[num_byte]&(0xFFFF7F>>>(num_wavelength%8))); + } + } + public void setAllWavelengtshUnReserved(){ + if (withWLANs) + { + for (int i = 0; i < reservedWLANs.length; i++) + { + reservedWLANs[i] = false; + } + } + else + { + int num_bytes=((BitmapLabelSet)this.getAvailableLabels().getLabelSet()).getBytesBitmapReserved().length; + for (int i=0;i>>(num_wavelength%8)))==0); + } + + } + public boolean isWavelengthUnreserved(int num_wavelength){//si es true esta unreserved + if (withWLANs) + { + return (!reservedWLANs[num_wavelength]); + } + else + { + int num_byte=num_wavelength/8; + if (((BitmapLabelSet)this.getAvailableLabels().getLabelSet()).getBytesBitmapReserved()==null){ + return false; + } + else{ + return ((((BitmapLabelSet)this.getAvailableLabels().getLabelSet()).getBytesBitmapReserved()[num_byte]&(0x80>>>(num_wavelength%8)))==0); + } + } + } + + + public String toString(){ + String ret=""; +// if (linkType!=null){ +// ret=ret+linkType.toString()+"\t"; +// } +// if (linkID!=null){ +// ret=ret+linkID.toString()+"\t"; +// } +// if (localInterfaceIPAddress!=null){ +// ret=ret+localInterfaceIPAddress.toString()+"\r\n"; +// } +// if (remoteInterfaceIPAddress!=null){ +// ret=ret+remoteInterfaceIPAddress.toString()+"\r\n"; +// } + + if (maximumBandwidth!=null){ + ret=ret+maximumBandwidth.toStringShort()+"\t"; + } + if (maximumReservableBandwidth!=null){ + ret=ret+maximumReservableBandwidth.toString()+"\t"; + } + + if (unreservedBandwidth!=null){ + ret=ret+unreservedBandwidth.toStringShort()+"\t"; + } + + if (administrativeGroup!=null){ + ret=ret+administrativeGroup.toString()+"\t"; + } + + if (remoteASNumber!=null){ + ret=ret+remoteASNumber.toString()+"\t"; + } + + if (iPv4RemoteASBRID!=null){ + ret=ret+iPv4RemoteASBRID.toString()+"\t"; + } + + if (availableLabels!= null){ + ret=ret+availableLabels.toString()+"\r\n"; + } + + if (iPv4LocalNode!=null){ + ret=ret+iPv4LocalNode.toString()+"\r\n"; + } + + if (iPv4RemoteNode!=null){ + ret=ret+iPv4RemoteNode.toString()+"\r\n"; + } + + if(linkProtectionBGPLS!=null){ + ret=ret+linkProtectionBGPLS.toString()+"\r\n"; + } + + if(trafficEngineeringMetric!=null){ + ret=ret+trafficEngineeringMetric.toString()+"\r\n"; + } + + if(metric!=null){ + ret=ret+metric.toString()+"\r\n"; + } + + if(defaultTEMetric!=null){ + ret=ret+defaultTEMetric.toString()+"\r\n"; + } + + if(this.mfOTF !=null){ + ret=ret+mfOTF.toString()+"\r\n"; + } + + + if(this.trans !=null){ + ret=ret+trans.toString()+"\r\n"; + } + if(undirLinkDelay!=null){ + ret=ret+undirLinkDelay.toString()+"\r\n"; + } + if(minMaxUndirLinkDelay!=null){ + ret=ret+minMaxUndirLinkDelay.toString()+"\r\n"; + } + if(undirDelayVar!=null){ + ret=ret+undirDelayVar.toString()+"\r\n"; + } + + if(undirLinkLoss!=null){ + ret=ret+undirLinkLoss.toString()+"\r\n"; + } + if(undirResidualBw!=null){ + ret=ret+undirResidualBw.toString()+"\r\n"; + } + if(undirAvailableBw!=null){ + ret=ret+undirAvailableBw.toString()+"\r\n"; + } + + if(undirUtilizedBw!=null){ + ret=ret+undirUtilizedBw.toString()+"\r\n"; + } + + return ret; + } + + public boolean isVlanLink() { + return vlanLink; + } + + public void setVlanLink(boolean vlanLink) { + this.vlanLink = vlanLink; + } + + public int getVlan() { + return vlan; + } + + public void setVlan(int vlan) { + this.vlan = vlan; + } + + public void setiPv4LocalNode(IPv4RouterIDLocalNodeLinkAttribTLV iPv4RouterIDLocalNode) { + this.iPv4LocalNode = iPv4RouterIDLocalNode; + } + public IPv4RouterIDLocalNodeLinkAttribTLV getiPv4LocalNode() { + return iPv4LocalNode; + } + + public MetricLinkAttribTLV getMetric() { + return metric; + } + + public void setMetric(MetricLinkAttribTLV metric) { + this.metric = metric; + } + + public LinkProtectionTypeLinkAttribTLV getLinkProtectionBGPLS() { + return linkProtectionBGPLS; + } + + public void setLinkProtectionBGPLS(LinkProtectionTypeLinkAttribTLV linkProtectionBGPLS) { + this.linkProtectionBGPLS = linkProtectionBGPLS; + } + + public DefaultTEMetricLinkAttribTLV getDefaultTEMetric() { + return defaultTEMetric; + } + + public void setDefaultTEMetric(DefaultTEMetricLinkAttribTLV defaultTEMetric) { + this.defaultTEMetric = defaultTEMetric; + } + + public MF_OTPAttribTLV getMfOTF() { + return mfOTF; + } + + public void setMfOTF(MF_OTPAttribTLV mfOTF) { + this.mfOTF = mfOTF; + } + + public TransceiverClassAndAppAttribTLV getTrans() { + return trans; + } + + public void setTrans(TransceiverClassAndAppAttribTLV trans) { + this.trans = trans; + } + + + + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/WSONInformation.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/WSONInformation.java new file mode 100644 index 000000000..c67f3a826 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/WSONInformation.java @@ -0,0 +1,74 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb; + +import es.tid.ospf.ospfv2.lsa.tlv.subtlv.AvailableLabels; + +public class WSONInformation { + /** + * In case the Network is WSON, this is the list of available Labels + */ + private AvailableLabels commonAvailableLabels; + + /** + * In case the Network is WSON, this is the number of wavelengths. -1 means it is not WSON. + */ + private int numLambdas=-1; + int grid=0; + int cs=0; + int nMin=0; + + public int getGrid() { + return grid; + } + + public void setGrid(int grid) { + this.grid = grid; + } + + public int getCs() { + return cs; + } + + public void setCs(int cs) { + this.cs = cs; + } + + + public int getnMin() { + return nMin; + } + + public void setnMin(int nMin) { + this.nMin = nMin; + } + + public AvailableLabels getCommonAvailableLabels() { + return commonAvailableLabels; + } + + public void setCommonAvailableLabels(AvailableLabels commonAvailableLabels) { + this.commonAvailableLabels = commonAvailableLabels; + } + + public int getNumLambdas() { + return numLambdas; + } + + public void setNumLambdas(int numLambdas) { + this.numLambdas = numLambdas; + } + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/WSONListener.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/WSONListener.java new file mode 100644 index 000000000..31b35b441 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/WSONListener.java @@ -0,0 +1,19 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb; + +public interface WSONListener { + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterController.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterController.java new file mode 100644 index 000000000..463e300c4 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterController.java @@ -0,0 +1,272 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb.controllers; + +import java.io.File; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.locks.Lock; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.jgrapht.graph.SimpleDirectedWeightedGraph; +import org.w3c.dom.CharacterData; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import eu.teraflow.tid.tedb.DomainTEDB; +import eu.teraflow.tid.tedb.IntraDomainEdge; +import eu.teraflow.tid.tedb.SimpleTEDB; +import eu.teraflow.tid.tedb.TE_Information; +import eu.teraflow.tid.tedb.elements.RouterInfoPM; + +/** + * + * @author jaume i la humiltat + * + * + * Class that receives a DomainTED and updates. Then it dies. + */ + +public class TEDUpdaterController extends Thread +{ + protected Hashtable interDomainLinks = new Hashtable(); + protected ArrayList ips = null; + protected ArrayList ports = null; + protected String topologyPathNodes = ""; + protected String topologyPathLinks = ""; + protected SimpleTEDB TEDB; + protected Logger log; + protected Lock lock = null; + protected String interDomainFile = null; + + public TEDUpdaterController(){}; + + public TEDUpdaterController(String ip, String port, String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log) + { + ips = new ArrayList(); + ports = new ArrayList(); + + ips.add(ip); + ports.add(port); + + this.topologyPathLinks = topologyPathLinks; + this.topologyPathNodes = topologyPathNodes; + this.TEDB = (SimpleTEDB)ted; + this.log = log; + } + + + public TEDUpdaterController(String ip, String port, String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log, Lock lock) + { + ips = new ArrayList(); + ports = new ArrayList(); + + ips.add(ip); + ports.add(port); + + this.topologyPathLinks = topologyPathLinks; + this.topologyPathNodes = topologyPathNodes; + this.TEDB = (SimpleTEDB)ted; + this.log = log; + this.lock = lock; + } + + public TEDUpdaterController(ArrayList ips, ArrayListports , String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log) + { + this.ips = ips; + this.ports = ports; + this.topologyPathLinks = topologyPathLinks; + this.topologyPathNodes = topologyPathNodes; + this.TEDB = (SimpleTEDB)ted; + this.log = log; + } + + public static void parseRemainingLinksFromXML(DomainTEDB TEDB, String interDomainFile) + { + Hashtable interDomainLinks = readInterDomainFile(interDomainFile); + Map map = interDomainLinks; + Iterator> it = map.entrySet().iterator(); + while (it.hasNext()) + { + Map.Entry entry = it.next(); + + MyEdge edgeAux = entry.getValue(); + + IntraDomainEdge edge= new IntraDomainEdge(); + edge.setSrc_if_id(new Long(edgeAux.source_port)); + edge.setDst_if_id(new Long(edgeAux.dest_port)); + + TE_Information tE_info = new TE_Information(); + tE_info.setNumberWLANs(15); + tE_info.initWLANs(); + + tE_info.setVlanLink(true); + tE_info.setVlan(edgeAux.vlan); + + edge.setTE_info(tE_info); + + + System.out.println("Adding InterDomain Edge!!::Vlan::"+edgeAux.vlan); + + + SimpleDirectedWeightedGraph sdwg = ((SimpleTEDB)TEDB).getNetworkGraph(); + if (!sdwg.containsVertex(new RouterInfoPM(edgeAux.source))) + { + sdwg.addVertex(new RouterInfoPM(edgeAux.source)); + } + + if (!sdwg.containsVertex(new RouterInfoPM(edgeAux.dest))) + { + sdwg.addVertex(new RouterInfoPM(edgeAux.dest)); + } + + + ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(new RouterInfoPM(edgeAux.source), new RouterInfoPM(edgeAux.dest), edge); + } + } + + + public static Hashtable readInterDomainFile(String interDomainFile) + { + System.out.println("Parsing intradomain File"); + Hashtable interDomainLinks = new Hashtable(); + try + { + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + File confFile = new File(interDomainFile); + Document doc = builder.parse(confFile); + + NodeList list_nodes_Edges = doc.getElementsByTagName("edge"); + System.out.println("num edges: " + list_nodes_Edges.getLength()); + for (int i = 0; i < list_nodes_Edges.getLength(); i++) + { + Element nodes_servers = (Element) list_nodes_Edges.item(i); + String source = getCharacterDataFromElement((Element) nodes_servers.getElementsByTagName("source").item(0)); + String dest = getCharacterDataFromElement((Element) nodes_servers.getElementsByTagName("dest").item(0)); + Integer vlan = Integer.parseInt(getCharacterDataFromElement((Element) nodes_servers.getElementsByTagName("vlan").item(0))); + String direction = getCharacterDataFromElement((Element) nodes_servers.getElementsByTagName("direction").item(0)); + int source_port = Integer.parseInt(getCharacterDataFromElement((Element) nodes_servers.getElementsByTagName("source_port").item(0))); + int dest_port = Integer.parseInt(getCharacterDataFromElement((Element) nodes_servers.getElementsByTagName("dest_port").item(0))); + + System.out.println("Adding IntraDomain Link! source: "+source+", dest: "+dest+", source_port: "+source_port+", dest_port: "+dest_port); + + MyEdge auxEdge = new TEDUpdaterController().new MyEdge(source, dest, vlan, source_port, dest_port); + interDomainLinks.put(auxEdge.hashCode(), auxEdge); + + if (direction.equals("bidirectional")) + { + MyEdge reverseEdge = new TEDUpdaterController().new MyEdge(dest, source, vlan, source_port, dest_port); + interDomainLinks.put(reverseEdge.hashCode(), reverseEdge); + } + } + } + catch (Exception e) + { + System.out.println(e.toString()); + } + + return interDomainLinks; + } + + private static String getCharacterDataFromElement(Element e) + { + Node child = e.getFirstChild(); + if (child instanceof CharacterData) + { + CharacterData cd = (CharacterData) child; + return cd.getData(); + } + else + { + return "?"; + } + } + + public class MyEdge + { + String source; + String dest; + Integer source_port; + Integer dest_port; + Integer vlan; + + MyEdge(String source, String dest) + { + this.source = source; + this.dest = dest; + } + + MyEdge(String source, String dest, Integer vlan, Integer source_port, Integer dest_port) + { + this.source = source; + this.dest = dest; + this.source_port = source_port; + this.dest_port = dest_port; + this.vlan = vlan; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((dest == null) ? 0 : dest.hashCode()); + result = prime * result + + ((source == null) ? 0 : source.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; + MyEdge other = (MyEdge) obj; + if (dest == null) { + if (other.dest != null) + return false; + } else if (!dest.equals(other.dest)) + return false; + if (source == null) { + if (other.source != null) + return false; + } else if (!source.equals(other.source)) + return false; + return true; + } + + } + + public String getInterDomainFile() + { + return interDomainFile; + } + + public void setInterDomainFile(String interDomainFile) + { + this.interDomainFile = interDomainFile; + } + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterFloodlight.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterFloodlight.java new file mode 100644 index 000000000..9bea224fa --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterFloodlight.java @@ -0,0 +1,367 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb.controllers; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.concurrent.locks.Lock; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.w3c.dom.CharacterData; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import eu.teraflow.tid.tedb.DomainTEDB; +import eu.teraflow.tid.tedb.IntraDomainEdge; +import eu.teraflow.tid.tedb.SimpleTEDB; +import eu.teraflow.tid.tedb.TE_Information; +import eu.teraflow.tid.tedb.elements.RouterInfoPM; + +/** + * Thread that reads topology from Openflow controller and from XML if there are intradomain links + * @author jaume + * + */ + +public class TEDUpdaterFloodlight extends TEDUpdaterController +{ + public static String controllerName = "Floodlight"; + + + private String topologyPathLinks = "/wm/topology/links/json"; + private String topologyPathNodes = "/wm/core/controller/switches/json"; + + public TEDUpdaterFloodlight(String ip,String port, String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log) + { + super(); + ips = new ArrayList(); + ports = new ArrayList(); + + ips.add(ip); + ports.add(port); + this.TEDB = (SimpleTEDB)ted; + this.log = log; + } + + public TEDUpdaterFloodlight(String ip, String port, String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log, Lock lock) + { + super( ip, port, topologyPathLinks, topologyPathNodes, ted, log, lock); + } + + public TEDUpdaterFloodlight(ArrayList ips, ArrayListports , String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log) + { + super(ips, ports , topologyPathLinks, topologyPathNodes, ted, log); + } + + + + + + + @Override + public void run() + { + + if(interDomainFile != null) + { + interDomainLinks = TEDUpdaterController.readInterDomainFile(interDomainFile); + } + + String responseLinks = ""; + String responseNodes = ""; + + try + { + //log.info("TopologyUpdaterWLAN thread, Updating TEDB"); + + Hashtable nodes = new Hashtable(); + + + log.info("ips.size():"+ips.size()); + + for (int i = 0; i < ips.size(); i++) + { + responseNodes = queryForNodes(ips.get(i), ports.get(i)); + parseNodes(responseNodes, nodes, ips.get(i), ports.get(i)); + log.info("responseNodes:::"+responseNodes); + } + + for (int i = 0; i < ips.size(); i++) + { + responseLinks = queryForLinks(ips.get(i), ports.get(i)); + + log.info("responseLinks:::"+responseLinks); + + lock(); + parseLinks(responseLinks, nodes); + unlock(); + + } + + + //parseJSON("[{\"src-switch\":\"00:14:2c:59:e5:5e:2b:00\",\"src-port\":20,\"src-port-state\":0,\"dst-switch\":\"00:14:2c:59:e5:64:21:00\",\"dst-port\":19,\"dst-port-state\":0,\"type\":\"internal\"},{\"src-switch\":\"00:14:2c:59:e5:64:21:00\",\"src-port\":19,\"src-port-state\":0,\"dst-switch\":\"00:14:2c:59:e5:5e:2b:00\",\"dst-port\":20,\"dst-port-state\":0,\"type\":\"internal\"},{\"src-switch\":\"00:14:2c:59:e5:66:ed:00\",\"src-port\":9,\"src-port-state\":0,\"dst-switch\":\"00:14:2c:59:e5:64:21:00\",\"dst-port\":20,\"dst-port-state\":0,\"type\":\"internal\"},{\"src-switch\":\"00:14:2c:59:e5:64:21:00\",\"src-port\":20,\"src-port-state\":0,\"dst-switch\":\"00:14:2c:59:e5:66:ed:00\",\"dst-port\":9,\"dst-port-state\":0,\"type\":\"internal\"}]"); + //System.out.println(response); + } + catch (Exception e) + { + log.info(e.toString()); + } + } + + + + private void parseNodes(String response, Hashtable routerInfoList, String ip, String port) + { + try + { + JSONParser parser = new JSONParser(); + Object obj = parser.parse(response); + + JSONArray msg = (JSONArray) obj; + Iterator iterator = msg.iterator(); + while (iterator.hasNext()) + { + JSONObject jsonObject = (JSONObject) iterator.next(); + + RouterInfoPM rInfo = new RouterInfoPM(); + rInfo.setMacAddress((String)jsonObject.get("mac")); + rInfo.setRouterID((String)jsonObject.get("dpid")); + rInfo.setControllerType(TEDUpdaterFloodlight.controllerName); + + + JSONArray ports = (JSONArray) jsonObject.get("ports"); + Iterator portIterator = ports.iterator(); + while (portIterator.hasNext()) + { + JSONObject jsonPortObject = (JSONObject) portIterator.next(); + rInfo.setMacAddress((String)jsonPortObject.get("hardwareAddress")); + } + + log.info("(String)((JSONObject)jsonObject.get(description)).get(manufacturer)::"+(String)((JSONObject)jsonObject.get("description")).get("manufacturer")); + rInfo.setRouterType((String)((JSONObject)jsonObject.get("description")).get("manufacturer")); + rInfo.setConfigurationMode("Openflow"); + + rInfo.setControllerIdentifier(ip, port); + rInfo.setControllerIP(ip); + rInfo.setControllerPort(port); + rInfo.setHardware((String)((JSONObject)jsonObject.get("description")).get("hardware")); + + routerInfoList.put(rInfo.getRouterID(),rInfo); + + + log.info("Adding Vertex::"+rInfo); + ((SimpleTEDB)TEDB).getNetworkGraph().addVertex(rInfo); + } + } + catch (Exception e) + { + log.info(e.toString()); + } + } + + private void parseLinks(String links,Hashtable nodes) + { + try { + //log.info("Inside parseJSON"); + JSONParser parser = new JSONParser(); + Object obj = parser.parse(links); + + JSONArray msg = (JSONArray) obj; + Iterator iterator = msg.iterator(); + while (iterator.hasNext()) + { + JSONObject jsonObject = (JSONObject) iterator.next(); + //System.out.println(jsonObject.get("src-switch")); + IntraDomainEdge edge= new IntraDomainEdge(); + + RouterInfoPM source = nodes.get(jsonObject.get("src-switch")); + RouterInfoPM dest = nodes.get(jsonObject.get("dst-switch")); + + + //((SimpleTEDB)TEDB).getNetworkGraph().addVertex(source); + //((SimpleTEDB)TEDB).getNetworkGraph().addVertex(dest); + + log.info("Adding Vertex->"+source+" hashcode:"+source.hashCode()); + log.info("Adding Vertex->"+dest+" hashcode:"+dest.hashCode()); + + edge.setSrc_if_id((Long)jsonObject.get("src-port")); + edge.setDst_if_id((Long)jsonObject.get("dst-port")); + + + // This is a big problem because info is not initialized from file + // and the controller doesn't give information about how many wlans + // the are + + TE_Information tE_info = new TE_Information(); + tE_info.setNumberWLANs(15); + tE_info.initWLANs(); + + if (interDomainFile != null) + { + completeTE_Information(tE_info, source.getRouterID(), dest.getRouterID()); + } + + edge.setTE_info(tE_info); + + String isBidirectional = (String)jsonObject.get("direction"); + + + + //log.info("isBidirectional::"+isBidirectional); + + if ((1==1)||(isBidirectional != null) && (isBidirectional.equals("bidirectional"))) + { + //((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge); + + TE_Information tE_infoOtherWay = new TE_Information(); + tE_infoOtherWay.setNumberWLANs(15); + tE_infoOtherWay.initWLANs(); + IntraDomainEdge edgeOtherWay= new IntraDomainEdge(); + + edgeOtherWay.setSrc_if_id((Long)jsonObject.get("dst-port")); + edgeOtherWay.setDst_if_id((Long)jsonObject.get("src-port")); + edgeOtherWay.setTE_info(tE_infoOtherWay); + + ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge); + ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(dest, source, edgeOtherWay); + + completeTE_Information(tE_info, dest.getRouterID(), source.getRouterID()); + + log.info("source::"+source); + log.info("dest::"+dest); + log.info("edgeOtherWay::"+edgeOtherWay); + log.info("edge::"+edge); + //log.info("Adding two!"); + } + else + { + ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge); + } + + //log.info("Edge added:"+edge); + //log.info(((SimpleTEDB)TEDB).getIntraDomainLinks().toString()); + } + //parseRemainingLinksFromXML(nodes); + + } + catch (Exception e) + { + log.info(e.toString()); + } + } + + private void completeTE_Information(TE_Information tE_info, String source, String dest) + { + MyEdge auxEdge = new MyEdge(source, dest); + MyEdge completEdge = interDomainLinks.get(auxEdge.hashCode()); + if ((completEdge != null)&&(completEdge.vlan != null)) + { + tE_info.setVlanLink(true); + tE_info.setVlan(completEdge.vlan); + //If it has been found it will be removed so the rest can be proccessed later + interDomainLinks.remove(completEdge.vlan); + } + else + { + tE_info.setVlanLink(false); + } + } + + private String queryForLinks(String ip, String port) + { + String response = ""; + try + { + URL topoplogyURL = new URL("http://"+ip+":"+port+topologyPathLinks); + + //log.info("URL::"+"http://"+ip+":"+port+topologyPathLinks); + + URLConnection yc = topoplogyURL.openConnection(); + BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream())); + String inputLine; + + while ((inputLine = in.readLine()) != null) + { + response = response + inputLine; + } + } + catch (Exception e) + { + log.info(e.toString()); + } + return response; + } + + private String queryForNodes(String ip, String port) + { + String response = ""; + try + { + URL topoplogyURL = new URL("http://"+ip+":"+port+topologyPathNodes); + + log.info("http://+port+topologyPathNodes:::"+"http://"+ip+":"+port+topologyPathNodes); + + URLConnection yc = topoplogyURL.openConnection(); + BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream())); + + String inputLine; + while ((inputLine = in.readLine()) != null) + { + response = response + inputLine; + } + in.close(); + } + catch (Exception e) + { + log.info(e.toString()); + } + return response; + } + + private void lock() + { + if (lock != null) + { + lock.lock(); + } + } + + private void unlock() + { + if (lock != null) + { + lock.unlock(); + } + } + + private String getCharacterDataFromElement(Element e) { + Node child = e.getFirstChild(); + if (child instanceof CharacterData) { + CharacterData cd = (CharacterData) child; + return cd.getData(); + } else { + return "?"; + } + } +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterNOX.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterNOX.java new file mode 100644 index 000000000..fb2c3c51d --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterNOX.java @@ -0,0 +1,419 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb.controllers; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.concurrent.locks.Lock; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import eu.teraflow.tid.tedb.DomainTEDB; +import eu.teraflow.tid.tedb.IntraDomainEdge; +import eu.teraflow.tid.tedb.SimpleTEDB; +import eu.teraflow.tid.tedb.TE_Information; +import eu.teraflow.tid.tedb.elements.RouterInfoPM; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; + +public class TEDUpdaterNOX extends TEDUpdaterController +{ + public static String controllerName = "NOX"; + private Hashtable interDomainLinks = new Hashtable(); + + + //Overwritten father variables and fixing the topology urls in code + private String topologyPathNodes = "/get_vtopology/"; + private String topologyPathLinks = "/get_graph/";//?? + + public TEDUpdaterNOX(String ip, String port, String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log) + { + super( ip, port, topologyPathLinks, topologyPathNodes, ted, log); + } + + public TEDUpdaterNOX(String ip, String port, String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log, Lock lock) + { + super( ip, port, topologyPathLinks, topologyPathNodes, ted, log, lock); + } + + public TEDUpdaterNOX(ArrayList ips, ArrayListports , String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log) + { + super(ips, ports , topologyPathLinks, topologyPathNodes, ted, log); + } + + + @Override + public void run() + { + + if(interDomainFile != null) + { + interDomainLinks = TEDUpdaterController.readInterDomainFile(interDomainFile); + } + + String responseLinks = ""; + String responseNodes = ""; + + try + { + + Hashtable nodes = new Hashtable(); + + for (int i = 0; i < ips.size(); i++) + { + responseNodes = queryForNodes(ips.get(i), ports.get(i));//query for topology + parseNodes(responseNodes, nodes, ips.get(i), ports.get(i)); + log.info("responseNodes:::"+responseNodes); + } + + } + catch (Exception e) + { + log.info(e.toString()); + } + } + + + private String BristoltoFloodlight(String BristolFormat) + { + String floodFormat = new String(BristolFormat); + //Por algo se me conoce como el hacker + for (int i = 2; i < floodFormat.length(); i += 3) + { + floodFormat = floodFormat.substring(0, i) + ":" + floodFormat.substring(i, floodFormat.length()); + } + log.info("BristolFormat--> " + BristolFormat + ", floodFormat-->" + floodFormat); + return floodFormat; + } + + private void parseNodes(String response, Hashtable routerInfoList, String ip, String port) + { + try + { + JSONParser parser = new JSONParser(); + Object obj = parser.parse(response); + + JSONObject jsonaux=(JSONObject) obj; + Iterator iterkeys=jsonaux.keySet().iterator(); + Hashtable nodes= new Hashtable(); + while (iterkeys.hasNext()) { + String dpid = iterkeys.next(); + System.out.println("Key: "+dpid.replace("-", ":")); + RouterInfoPM rInfo = new RouterInfoPM(); + + rInfo.setRouterID(dpid.replace("-", ":"));//Bristol to floodlight? + rInfo.setConfigurationMode("Openflow"); + rInfo.setControllerType(TEDUpdaterNOX.controllerName); + + rInfo.setControllerIdentifier(ip, port); + rInfo.setControllerIP(ip); + rInfo.setControllerPort(port); + + routerInfoList.put(rInfo.getRouterID(),rInfo); + nodes.put(dpid.replace("-", ":"),rInfo); + ((SimpleTEDB)TEDB).getNetworkGraph().addVertex(rInfo); + } + //Getting Links + Iterator nodeiter=nodes.keySet().iterator(); + while (nodeiter.hasNext()){ + String node= nodeiter.next(); + parseLinks(node, (String)jsonaux.get(node.replace(":", "-")).toString(), nodes); + } + //parseLinks(dpid, jsonarray) + } + catch (Exception e) + { + log.info(e.toString()); + } + } + + private void parseLinks(String dpid,String links, Hashtable nodes) + { + try { + //log.info("Inside parseJSON"); + JSONParser parser = new JSONParser(); + Object obj = parser.parse(links); + + JSONArray msg = (JSONArray) obj; + Iterator iterator = msg.iterator(); + while (iterator.hasNext()) + { + JSONObject jsonObject = (JSONObject) iterator.next(); + //System.out.println(jsonObject.get("src-switch")); + IntraDomainEdge edge= new IntraDomainEdge(); + + String labels = (String) jsonObject.get("labels");//?? + String destnode = ((String) jsonObject.get("peer_node")).replace("-", ":"); + String type = (String) jsonObject.get("port_type"); + + RouterInfoPM source = nodes.get(dpid); + RouterInfoPM dest = nodes.get(destnode); + + //((SimpleTEDB)TEDB).getNetworkGraph().addVertex(source); + //((SimpleTEDB)TEDB).getNetworkGraph().addVertex(dest); + + System.out.println("Srcnode: "+dpid); + System.out.println("Dstnode: "+destnode); + + System.out.println("Srcport: "+jsonObject.get("port_id")); + System.out.println("Dstport: "+jsonObject.get("peer_port")); + + if ((dest!= null)&&(source!=null)){ + + + edge.setSrc_if_id(Long.parseLong((String)jsonObject.get("port_id"))); + edge.setDst_if_id(Long.parseLong((String)jsonObject.get("peer_port"))); + + edge.setType(type); + + // This is a big problem because info is not initialized from file + // and the controller doesn't give information about how many wlans + // the are + + TE_Information tE_info = new TE_Information(); + System.out.println("Labels: Original ("+labels+") and Parsed ("+labels.substring(labels.indexOf(",")+1,labels.indexOf("]"))+")"); + tE_info.setNumberWLANs(Integer.parseInt(labels.substring(labels.indexOf(",")+1,labels.indexOf("]")))); + tE_info.initWLANs(); + + if (interDomainFile != null) + { + completeTE_Information(tE_info, source.getRouterID(), dest.getRouterID()); + } + + edge.setTE_info(tE_info); + + + edge.setDirectional(true); + //Bidirectional case? See other TEDUpdaters. + + ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge); + + } else { + System.out.println("Link with an unknown node. Ingnoring..."); + } + //log.info("Edge added:"+edge); + //log.info(((SimpleTEDB)TEDB).getIntraDomainLinks().toString()); + } + //parseRemainingLinksFromXML(nodes); + + + } + catch (Exception e) + { + log.info(e.toString()); + } + } + + +// private void parseLinks(String links,Hashtable nodes) +// { +// try { +// //log.info("Inside parseJSON"); +// JSONParser parser = new JSONParser(); +// Object obj = parser.parse(links); +// +// JSONArray msg = (JSONArray) obj; +// Iterator iterator = msg.iterator(); +// while (iterator.hasNext()) +// { +// JSONObject jsonObject = (JSONObject) iterator.next(); +// //System.out.println(jsonObject.get("src-switch")); +// IntraDomainEdge edge= new IntraDomainEdge(); +// +// JSONObject jsonObject_src = (JSONObject) jsonObject.get("src"); +// JSONObject jsonObject_dst = (JSONObject) jsonObject.get("dst"); +// +// RouterInfoPM source = nodes.get(BristoltoFloodlight((String)jsonObject_src.get("dpid"))); +// RouterInfoPM dest = nodes.get(BristoltoFloodlight((String)jsonObject_dst.get("dpid"))); +// +// //((SimpleTEDB)TEDB).getNetworkGraph().addVertex(source); +// //((SimpleTEDB)TEDB).getNetworkGraph().addVertex(dest); +// +// log.info("Adding Vertex->"+source+" hashcode:"+source.hashCode()); +// log.info("Adding Vertex->"+dest+" hashcode:"+dest.hashCode()); +// +// edge.setSrc_if_id((Long)jsonObject_src.get("port_no")); +// edge.setDst_if_id((Long)jsonObject_dst.get("port_no")); +// +// +// // This is a big problem because info is not initialized from file +// // and the controller doesn't give information about how many wlans +// // the are +// +// TE_Information tE_info = new TE_Information(); +// tE_info.setNumberWLANs(15); +// tE_info.initWLANs(); +// +// if (interDomainFile != null) +// { +// completeTE_Information(tE_info, source.getRouterID(), dest.getRouterID()); +// } +// +// edge.setTE_info(tE_info); +// +// String isBidirectional = (String)jsonObject.get("direction"); +// +// +// // En Bristol los enlaces son unidirecctionales, pero asumimos que hay uno en una direccion +// // esta el otro +// isBidirectional = "bidirectional"; +// +// //log.info("isBidirectional::"+isBidirectional); +// +// if ((1==1)||(isBidirectional != null) && (isBidirectional.equals("bidirectional"))) +// { +// //((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge); +// +// TE_Information tE_infoOtherWay = new TE_Information(); +// tE_infoOtherWay.setNumberWLANs(15); +// tE_infoOtherWay.initWLANs(); +// IntraDomainEdge edgeOtherWay= new IntraDomainEdge(); +// +// edgeOtherWay.setSrc_if_id((Long)jsonObject_src.get("port_no")); +// edgeOtherWay.setDst_if_id((Long)jsonObject_dst.get("port_no")); +// edgeOtherWay.setTE_info(tE_infoOtherWay); +// +// ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge); +// ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(dest, source, edgeOtherWay); +// +// completeTE_Information(tE_info, dest.getRouterID(), source.getRouterID()); +// +// log.info("source::"+source); +// log.info("dest::"+dest); +// log.info("edgeOtherWay::"+edgeOtherWay); +// log.info("edge::"+edge); +// //log.info("Adding two!"); +// } +// else +// { +// ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge); +// } +// +// //log.info("Edge added:"+edge); +// //log.info(((SimpleTEDB)TEDB).getIntraDomainLinks().toString()); +// } +// //parseRemainingLinksFromXML(nodes); +// +// +// } +// catch (Exception e) +// { +// log.info(UtilsFunctions.exceptionToString(e)); +// } +// } + + private void completeTE_Information(TE_Information tE_info, String source, String dest) + { + MyEdge auxEdge = new MyEdge(source, dest); + MyEdge completEdge = interDomainLinks.get(auxEdge.hashCode()); + if ((completEdge != null)&&(completEdge.vlan != null)) + { + tE_info.setVlanLink(true); + tE_info.setVlan(completEdge.vlan); + //If it has been found it will be removed so the rest can be proccessed later + interDomainLinks.remove(completEdge.vlan); + } + else + { + tE_info.setVlanLink(false); + } + } + + private String queryForLinks(String ip, String port) + { + String response = ""; + try + { + URL topoplogyURL = new URL("http://"+ip+":"+port+topologyPathLinks); + + log.info("URL::"+"http://"+ip+":"+port+topologyPathLinks); + + URLConnection yc = topoplogyURL.openConnection(); + BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream())); + String inputLine; + + while ((inputLine = in.readLine()) != null) + { + response = response + inputLine; + } + } + catch (Exception e) + { + log.info(e.toString()); + } + return response; + } + + private String queryForNodes(String ip, String port) + { + String response = ""; + try + { + URL topoplogyURL = new URL("http://"+ip+":"+port+topologyPathNodes); + + log.info("http://+port+topologyPathNodes:::"+"http://"+ip+":"+port+topologyPathNodes); + + URLConnection yc = topoplogyURL.openConnection(); + BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream())); + + String inputLine; + while ((inputLine = in.readLine()) != null) + { + response = response + inputLine; + } + in.close(); + } + catch (Exception e) + { + log.info(e.toString()); + } + return response; + } + + public String getInterDomainFile() + { + return interDomainFile; + } + + public void setInterDomainFile(String interDomainFile) + { + this.interDomainFile = interDomainFile; + } + + + private void lock() + { + if (lock != null) + { + lock.lock(); + } + } + + private void unlock() + { + if (lock != null) + { + lock.unlock(); + } + } +} + diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterODL.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterODL.java new file mode 100644 index 000000000..a1a8c0e6f --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterODL.java @@ -0,0 +1,351 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb.controllers; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.concurrent.locks.Lock; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.w3c.dom.CharacterData; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import eu.teraflow.tid.tedb.DomainTEDB; +import eu.teraflow.tid.tedb.IntraDomainEdge; +import eu.teraflow.tid.tedb.SimpleTEDB; +import eu.teraflow.tid.tedb.TE_Information; +import eu.teraflow.tid.tedb.elements.RouterInfoPM; + + + +/** + * Thread that reads topology from Openflow controller and from XML if there are intradomain links + * @author jaume + * + */ + +public class TEDUpdaterODL extends TEDUpdaterController +{ + public static String controllerName = "ODL"; + + + private String topologyPathLinks = "/controller/nb/v2/topology/default"; + private String topologyPathNodes = "/controller/nb/v2/switchmanager/default/nodes"; + + public TEDUpdaterODL(String ip,String port, String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log) + { + super(); + ips = new ArrayList(); + ports = new ArrayList(); + + ips.add(ip); + ports.add(port); + this.TEDB = (SimpleTEDB)ted; + this.log = log; + } + + public TEDUpdaterODL(String ip, String port, String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log, Lock lock) + { + super( ip, port, topologyPathLinks, topologyPathNodes, ted, log, lock); + } + + public TEDUpdaterODL(ArrayList ips, ArrayListports , String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log) + { + super(ips, ports , topologyPathLinks, topologyPathNodes, ted, log); + } + + + + + + + @Override + public void run() + { + + if(interDomainFile != null) + { + interDomainLinks = TEDUpdaterController.readInterDomainFile(interDomainFile); + } + + String responseLinks = ""; + String responseNodes = ""; + + try + { + + Hashtable nodes = new Hashtable(); + + + log.info("ips.size():"+ips.size()); + log.info("ODL updates_______________________________________________________START____"); + for (int i = 0; i < ips.size(); i++) + { + responseNodes = queryForNodes(ips.get(i), ports.get(i)); + parseNodes(responseNodes, nodes, ips.get(i), ports.get(i)); + } + + for (int i = 0; i < ips.size(); i++) + { + responseLinks = queryForLinks(ips.get(i), ports.get(i)); + lock(); + parseLinks(responseLinks, nodes); + unlock(); + + } + log.info("ODL updates_______________________________________________________END____"); + + + //parseJSON("[{\"src-switch\":\"00:14:2c:59:e5:5e:2b:00\",\"src-port\":20,\"src-port-state\":0,\"dst-switch\":\"00:14:2c:59:e5:64:21:00\",\"dst-port\":19,\"dst-port-state\":0,\"type\":\"internal\"},{\"src-switch\":\"00:14:2c:59:e5:64:21:00\",\"src-port\":19,\"src-port-state\":0,\"dst-switch\":\"00:14:2c:59:e5:5e:2b:00\",\"dst-port\":20,\"dst-port-state\":0,\"type\":\"internal\"},{\"src-switch\":\"00:14:2c:59:e5:66:ed:00\",\"src-port\":9,\"src-port-state\":0,\"dst-switch\":\"00:14:2c:59:e5:64:21:00\",\"dst-port\":20,\"dst-port-state\":0,\"type\":\"internal\"},{\"src-switch\":\"00:14:2c:59:e5:64:21:00\",\"src-port\":20,\"src-port-state\":0,\"dst-switch\":\"00:14:2c:59:e5:66:ed:00\",\"dst-port\":9,\"dst-port-state\":0,\"type\":\"internal\"}]"); + //System.out.println(response); + } + catch (Exception e) + { + log.info(e.toString()); + } + } + + + + private void parseNodes(String response, Hashtable routerInfoList, String ip, String port) + { + try + { + JSONParser parser = new JSONParser(); + Object obj = parser.parse(response); + + JSONArray msg = (JSONArray) ((JSONObject) obj).get("nodeProperties"); + Iterator iterator = msg.iterator(); + while (iterator.hasNext()) + { + JSONObject jsonObject = iterator.next(); + + RouterInfoPM rInfo = new RouterInfoPM(); + + String dpid = (String) (((JSONObject) jsonObject.get("node")).get("id")); + + rInfo.setRouterID(dpid); + rInfo.setConfigurationMode("Openflow"); + rInfo.setControllerType(TEDUpdaterODL.controllerName); + rInfo.setControllerIdentifier(ip, port); + rInfo.setControllerIP(ip); + rInfo.setControllerPort(port); + + routerInfoList.put(rInfo.getRouterID(),rInfo); + log.info("Adding Vertex::"+rInfo); + ((SimpleTEDB)TEDB).getNetworkGraph().addVertex(rInfo); + + + + } + } + catch (Exception e) + { + log.info(e.toString()); + } + } + + private void parseLinks(String links,Hashtable nodes) + { + try { + JSONParser parser = new JSONParser(); + Object obj = parser.parse(links); + + JSONArray msg = (JSONArray) ((JSONObject) obj).get("edgeProperties"); + Iterator iterator = msg.iterator(); + while (iterator.hasNext()) + { + JSONObject jsonObject = (JSONObject) iterator.next().get("edge"); + JSONObject jSrc = (JSONObject) jsonObject.get("headNodeConnector"); + JSONObject jDst = (JSONObject) jsonObject.get("tailNodeConnector"); + + + + IntraDomainEdge edge= new IntraDomainEdge(); + + RouterInfoPM source = nodes.get(((JSONObject) jSrc.get("node")).get("id"));// jsonObject.get("src-switch")); + RouterInfoPM dest = nodes.get(((JSONObject) jDst.get("node")).get("id"));// jsonObject.get("dst-switch")); + + + + edge.setSrc_if_id(Long.parseLong((String)jSrc.get("id"))); //jsonObject.get("src-port")); + edge.setDst_if_id(Long.parseLong((String)jDst.get("id"))); //jsonObject.get("dst-port")); + + // This is a big problem because info is not initialized from file + // and the controller doesn't give information about how many wlans + // the are + + TE_Information tE_info = new TE_Information(); + tE_info.setNumberWLANs(15); + tE_info.initWLANs(); + + if (interDomainFile != null) + { + completeTE_Information(tE_info, source.getRouterID(), dest.getRouterID()); + } + + edge.setTE_info(tE_info); + + String isBidirectional = (String)jsonObject.get("direction"); + + + + //log.info("isBidirectional::"+isBidirectional); + + if ((1==1)||(isBidirectional != null) && (isBidirectional.equals("bidirectional"))) + { + //((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge); + + TE_Information tE_infoOtherWay = new TE_Information(); + tE_infoOtherWay.setNumberWLANs(15); + tE_infoOtherWay.initWLANs(); + IntraDomainEdge edgeOtherWay= new IntraDomainEdge(); + + edgeOtherWay.setSrc_if_id(Long.parseLong((String)jDst.get("id"))); + edgeOtherWay.setDst_if_id(Long.parseLong((String)jSrc.get("id"))); + edgeOtherWay.setTE_info(tE_infoOtherWay); + + ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge); + ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(dest, source, edgeOtherWay); + + completeTE_Information(tE_info, dest.getRouterID(), source.getRouterID()); + + log.info("________EDGE_____"); + log.info("source::"+source); + log.info("dest::"+dest); + log.info("edgeOtherWay::"+edgeOtherWay); + log.info("edge::"+edge); + log.info("--------EDGE-----"); + } + else + { + ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge); + } + + //log.info("Edge added:"+edge); + //log.info(((SimpleTEDB)TEDB).getIntraDomainLinks().toString()); + } + //parseRemainingLinksFromXML(nodes); + + } + catch (Exception e) + { + log.info(e.toString()); + } + } + + private void completeTE_Information(TE_Information tE_info, String source, String dest) + { + MyEdge auxEdge = new MyEdge(source, dest); + MyEdge completEdge = interDomainLinks.get(auxEdge.hashCode()); + if ((completEdge != null)&&(completEdge.vlan != null)) + { + tE_info.setVlanLink(true); + tE_info.setVlan(completEdge.vlan); + //If it has been found it will be removed so the rest can be proccessed later + interDomainLinks.remove(completEdge.vlan); + } + else + { + tE_info.setVlanLink(false); + } + } + + private String queryForLinks(String ip, String port) + { + return query("http://"+ip+":"+port+topologyPathLinks); + } + + private String queryForNodes(String ip, String port) + { + return query("http://"+ip+":"+port+topologyPathNodes); + } + + private String query(String url) + { + log.info("Attempting to curl: "+url); + String response = ""; + try + { + String credentials = "admin:admin"; + String credentialsEncoded = "YWRtaW46YWRtaW4="; + + URL topoplogyURL = new URL(url); + URLConnection yc = topoplogyURL.openConnection(); + + HttpURLConnection httpcon = (HttpURLConnection) yc; + httpcon.setDoOutput(true); + httpcon.setRequestProperty("Content-Type", "application/json"); + httpcon.setRequestProperty("Authorization", "Basic "+credentialsEncoded); + + BufferedReader in = new BufferedReader( + new InputStreamReader( + httpcon.getInputStream())); + String inputLine; + + while ((inputLine = in.readLine()) != null) + { + response = response + inputLine; + } + in.close(); + return response; + } + catch (Exception e) + { + log.info(e.toString()); + } + + return ""; + + } + + + private void lock() + { + if (lock != null) + { + lock.lock(); + } + } + + private void unlock() + { + if (lock != null) + { + lock.unlock(); + } + } + + private String getCharacterDataFromElement(Element e) { + Node child = e.getFirstChild(); + if (child instanceof CharacterData) { + CharacterData cd = (CharacterData) child; + return cd.getData(); + } else { + return "?"; + } + } +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterRYU.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterRYU.java new file mode 100644 index 000000000..c1383b8b2 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterRYU.java @@ -0,0 +1,355 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb.controllers; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.concurrent.locks.Lock; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import eu.teraflow.tid.tedb.DomainTEDB; +import eu.teraflow.tid.tedb.IntraDomainEdge; +import eu.teraflow.tid.tedb.SimpleTEDB; +import eu.teraflow.tid.tedb.TE_Information; +import eu.teraflow.tid.tedb.elements.RouterInfoPM; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; + +/** + * Thread that reads topology from Openflow controller and from XML if there are intradomain links + * @author jaume + * + */ + + +public class TEDUpdaterRYU extends TEDUpdaterController +{ + public static String controllerName = "RYU"; + private Hashtable interDomainLinks = new Hashtable(); + + + //Overwritten father variables and fixing the topology urls in code + private String topologyPathNodes = "/v1.0/topology/switches"; + private String topologyPathLinks = "/v1.0/topology/links"; + + public TEDUpdaterRYU(String ip, String port, String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log) + { + super( ip, port, topologyPathLinks, topologyPathNodes, ted, log); + } + + public TEDUpdaterRYU(String ip, String port, String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log, Lock lock) + { + super( ip, port, topologyPathLinks, topologyPathNodes, ted, log, lock); + } + + public TEDUpdaterRYU(ArrayList ips, ArrayListports , String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log) + { + super(ips, ports , topologyPathLinks, topologyPathNodes, ted, log); + } + + + @Override + public void run() + { + + if(interDomainFile != null) + { + interDomainLinks = TEDUpdaterController.readInterDomainFile(interDomainFile); + } + + String responseLinks = ""; + String responseNodes = ""; + + try + { + + Hashtable nodes = new Hashtable(); + + for (int i = 0; i < ips.size(); i++) + { + responseNodes = queryForNodes(ips.get(i), ports.get(i)); + parseNodes(responseNodes, nodes, ips.get(i), ports.get(i)); + log.info("responseNodes:::"+responseNodes); + } + + for (int i = 0; i < ips.size(); i++) + { + responseLinks = queryForLinks(ips.get(i), ports.get(i)); + + log.info("responseLinks:::"+responseLinks); + + lock(); + parseLinks(responseLinks, nodes); + unlock(); + + } + + //parseJSON("[{\"src-switch\":\"00:14:2c:59:e5:5e:2b:00\",\"src-port\":20,\"src-port-state\":0,\"dst-switch\":\"00:14:2c:59:e5:64:21:00\",\"dst-port\":19,\"dst-port-state\":0,\"type\":\"internal\"},{\"src-switch\":\"00:14:2c:59:e5:64:21:00\",\"src-port\":19,\"src-port-state\":0,\"dst-switch\":\"00:14:2c:59:e5:5e:2b:00\",\"dst-port\":20,\"dst-port-state\":0,\"type\":\"internal\"},{\"src-switch\":\"00:14:2c:59:e5:66:ed:00\",\"src-port\":9,\"src-port-state\":0,\"dst-switch\":\"00:14:2c:59:e5:64:21:00\",\"dst-port\":20,\"dst-port-state\":0,\"type\":\"internal\"},{\"src-switch\":\"00:14:2c:59:e5:64:21:00\",\"src-port\":20,\"src-port-state\":0,\"dst-switch\":\"00:14:2c:59:e5:66:ed:00\",\"dst-port\":9,\"dst-port-state\":0,\"type\":\"internal\"}]"); + //System.out.println(response); + } + catch (Exception e) + { + log.info(e.toString()); + } + } + + + private String RYUtoFloodlight(String RYUFormat) + { + String floodFormat = new String(RYUFormat); + //Por algo se me conoce como el hacker + for (int i = 2; i < floodFormat.length(); i += 3) + { + floodFormat = floodFormat.substring(0, i) + ":" + floodFormat.substring(i, floodFormat.length()); + } + log.info("RYUFormat--> " + RYUFormat + ", floodFormat-->" + floodFormat); + return floodFormat; +} + + private void parseNodes(String response, Hashtable routerInfoList, String ip, String port) + { + try + { + JSONParser parser = new JSONParser(); + Object obj = parser.parse(response); + + JSONArray msg = (JSONArray) obj; + Iterator iterator = msg.iterator(); + while (iterator.hasNext()) + { + JSONObject jsonObject = (JSONObject) iterator.next(); + + log.info("(String)jsonObject.get(dpid)::"+(String)jsonObject.get("dpid")); + + RouterInfoPM rInfo = new RouterInfoPM(); + + rInfo.setRouterID(RYUtoFloodlight((String)jsonObject.get("dpid"))); + rInfo.setConfigurationMode("Openflow"); + rInfo.setControllerType(TEDUpdaterRYU.controllerName); + + rInfo.setControllerIdentifier(ip, port); + rInfo.setControllerIP(ip); + rInfo.setControllerPort(port); + + routerInfoList.put(rInfo.getRouterID(),rInfo); + + ((SimpleTEDB)TEDB).getNetworkGraph().addVertex(rInfo); + } + } + catch (Exception e) + { + log.info(e.toString()); + } + } + + private void parseLinks(String links,Hashtable nodes) + { + try { + //log.info("Inside parseJSON"); + JSONParser parser = new JSONParser(); + Object obj = parser.parse(links); + + JSONArray msg = (JSONArray) obj; + Iterator iterator = msg.iterator(); + while (iterator.hasNext()) + { + JSONObject jsonObject = (JSONObject) iterator.next(); + //System.out.println(jsonObject.get("src-switch")); + IntraDomainEdge edge= new IntraDomainEdge(); + + JSONObject jsonObject_src = (JSONObject) jsonObject.get("src"); + JSONObject jsonObject_dst = (JSONObject) jsonObject.get("dst"); + + RouterInfoPM source = nodes.get(RYUtoFloodlight((String)jsonObject_src.get("dpid"))); + RouterInfoPM dest = nodes.get(RYUtoFloodlight((String)jsonObject_dst.get("dpid"))); + + //((SimpleTEDB)TEDB).getNetworkGraph().addVertex(source); + //((SimpleTEDB)TEDB).getNetworkGraph().addVertex(dest); + + log.info("Adding Vertex->"+source+" hashcode:"+source.hashCode()); + log.info("Adding Vertex->"+dest+" hashcode:"+dest.hashCode()); + + edge.setSrc_if_id(Long.parseLong((String) jsonObject_src.get("port_no"))); + edge.setDst_if_id(Long.parseLong((String) jsonObject_dst.get("port_no"))); + + + // This is a big problem because info is not initialized from file + // and the controller doesn't give information about how many wlans + // the are + + TE_Information tE_info = new TE_Information(); + tE_info.setNumberWLANs(15); + tE_info.initWLANs(); + + if (interDomainFile != null) + { + completeTE_Information(tE_info, source.getRouterID(), dest.getRouterID()); + } + + edge.setTE_info(tE_info); + + String isBidirectional = (String)jsonObject.get("direction"); + + + // En RYU los enlaces son unidirecctionales, pero asumimos que hay uno en una direccion + // esta el otro + isBidirectional = "bidirectional"; + + //log.info("isBidirectional::"+isBidirectional); + + if ((1==1)||(isBidirectional != null) && (isBidirectional.equals("bidirectional"))) + { + //((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge); + + TE_Information tE_infoOtherWay = new TE_Information(); + tE_infoOtherWay.setNumberWLANs(15); + tE_infoOtherWay.initWLANs(); + IntraDomainEdge edgeOtherWay= new IntraDomainEdge(); + + edgeOtherWay.setSrc_if_id(Long.parseLong((String) jsonObject_src.get("port_no"))); + edgeOtherWay.setDst_if_id(Long.parseLong((String) jsonObject_dst.get("port_no"))); + edgeOtherWay.setTE_info(tE_infoOtherWay); + + ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge); + ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(dest, source, edgeOtherWay); + + completeTE_Information(tE_info, dest.getRouterID(), source.getRouterID()); + + log.info("source::"+source); + log.info("dest::"+dest); + log.info("edgeOtherWay::"+edgeOtherWay); + log.info("edge::"+edge); + } + else + { + ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge); + } + + //log.info("Edge added:"+edge); + //log.info(((SimpleTEDB)TEDB).getIntraDomainLinks().toString()); + } + //parseRemainingLinksFromXML(nodes); + + + } + catch (Exception e) + { + log.info(e.toString()); + } + } + + private void completeTE_Information(TE_Information tE_info, String source, String dest) + { + MyEdge auxEdge = new MyEdge(source, dest); + MyEdge completEdge = interDomainLinks.get(auxEdge.hashCode()); + if ((completEdge != null)&&(completEdge.vlan != null)) + { + tE_info.setVlanLink(true); + tE_info.setVlan(completEdge.vlan); + //If it has been found it will be removed so the rest can be proccessed later + interDomainLinks.remove(completEdge.vlan); + } + else + { + tE_info.setVlanLink(false); + } + } + + private String queryForLinks(String ip, String port) + { + String response = ""; + try + { + URL topoplogyURL = new URL("http://"+ip+":"+port+topologyPathLinks); + + log.info("URL::"+"http://"+ip+":"+port+topologyPathLinks); + + URLConnection yc = topoplogyURL.openConnection(); + BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream())); + String inputLine; + + while ((inputLine = in.readLine()) != null) + { + response = response + inputLine; + } + } + catch (Exception e) + { + log.info(e.toString()); + } + return response; + } + + private String queryForNodes(String ip, String port) + { + String response = ""; + try + { + URL topoplogyURL = new URL("http://"+ip+":"+port+topologyPathNodes); + + log.info("http://+port+topologyPathNodes:::"+"http://"+ip+":"+port+topologyPathNodes); + + URLConnection yc = topoplogyURL.openConnection(); + BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream())); + + String inputLine; + while ((inputLine = in.readLine()) != null) + { + response = response + inputLine; + } + in.close(); + } + catch (Exception e) + { + log.info(e.toString()); + } + return response; + } + + public String getInterDomainFile() + { + return interDomainFile; + } + + public void setInterDomainFile(String interDomainFile) + { + this.interDomainFile = interDomainFile; + } + + + private void lock() + { + if (lock != null) + { + lock.lock(); + } + } + + private void unlock() + { + if (lock != null) + { + lock.unlock(); + } + } +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterTREMA.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterTREMA.java new file mode 100644 index 000000000..a87fc3790 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/controllers/TEDUpdaterTREMA.java @@ -0,0 +1,449 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb.controllers; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.concurrent.locks.Lock; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; + +import com.metaparadigm.jsonrpc.JSONSerializer; + +import eu.teraflow.tid.tedb.DomainTEDB; +import eu.teraflow.tid.tedb.IntraDomainEdge; +import eu.teraflow.tid.tedb.SimpleTEDB; +import eu.teraflow.tid.tedb.TE_Information; +import eu.teraflow.tid.tedb.controllers.TEDUpdaterController.MyEdge; +import eu.teraflow.tid.tedb.elements.RouterInfoPM; + +public class TEDUpdaterTREMA extends TEDUpdaterController +{ + public static String controllerName = "TREMA"; + private Hashtable interDomainLinks = new Hashtable(); + + + //Overwritten father variables and fixing the topology urls in code + private String topologyPathNodes = "/get_topology/"; + private String topologyPathLinks = "/get_graph/";//?? + + public TEDUpdaterTREMA(String ip, String port, String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log) + { + super( ip, port, topologyPathLinks, topologyPathNodes, ted, log); + } + + public TEDUpdaterTREMA(String ip, String port, String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log, Lock lock) + { + super( ip, port, topologyPathLinks, topologyPathNodes, ted, log, lock); + } + + public TEDUpdaterTREMA(ArrayList ips, ArrayListports , String topologyPathLinks, String topologyPathNodes,DomainTEDB ted, Logger log) + { + super(ips, ports , topologyPathLinks, topologyPathNodes, ted, log); + } + + + @Override + public void run() + { + + if(interDomainFile != null) + { + interDomainLinks = TEDUpdaterController.readInterDomainFile(interDomainFile); + } + + String responseLinks = ""; + String responseNodes = ""; + + try + { + + Hashtable nodes = new Hashtable(); + + for (int i = 0; i < ips.size(); i++) + { + responseNodes = queryForNodes(ips.get(i), ports.get(i));//query for topology + parseNodes(responseNodes, nodes, ips.get(i), ports.get(i)); + log.info("responseNodes:::"+responseNodes); + } + + } + catch (Exception e) + { + log.info(e.toString()); + } + } + + + private String KDDItoFloodlight(String BristolFormat) + { + String floodFormat = new String(BristolFormat); + //Por algo se me conoce como el hacker + for (int i = 2; i < floodFormat.length(); i += 3) + { + floodFormat = floodFormat.substring(0, i) + ":" + floodFormat.substring(i, floodFormat.length()); + } + log.info("BristolFormat--> " + BristolFormat + ", floodFormat-->" + floodFormat); + return floodFormat; + } + + private void parseNodes(String response, Hashtable routerInfoList, String ip, String port) + { + try + { + JSONParser parser = new JSONParser(); + Object obj = parser.parse(response); + + JSONObject jsonaux=(JSONObject) obj; + String host=(String)jsonaux.get("hostConfig").toString(); + obj=parser.parse(host); + JSONObject jsonhost=(JSONObject) obj; + + //FIXME: This info has been taken from TREMA controller but is not used. Take a look if it's necessary + String OPS_Label=(String)jsonhost.get("OPS label"); + String Port_id=(String)jsonhost.get("Port_id"); + String reach_nodes=(String)jsonhost.get("Reachable nodes"); + String node_type=(String)jsonhost.get("nodeType");//Used for RouterType + + RouterInfoPM rInfo = new RouterInfoPM(); + String dpid=((String)jsonhost.get("Virtual_node_id")).replace("-", ":"); + rInfo.setRouterID(dpid);//Bristol to floodlight? + rInfo.setConfigurationMode("Openflow"); + rInfo.setControllerType(TEDUpdaterNOX.controllerName); + rInfo.setRouterType(node_type); + + rInfo.setReachable_nodes(parseReachability(reach_nodes)); + + rInfo.setControllerIdentifier(ip, port); + rInfo.setControllerIP(ip); + rInfo.setControllerPort(port); + + routerInfoList.put(rInfo.getRouterID(),rInfo); + ((SimpleTEDB)TEDB).getNetworkGraph().addVertex(rInfo); + //Getting Links + //parseLinks(???); + //parseLinks(dpid, jsonarray) + } + catch (Exception e) + { + log.info(e.toString()); + } + } + + private LinkedList parseReachability(String reach_nodes) { + boolean end=false; + int beginIndex=0; + LinkedList nodes= new LinkedList(); + reach_nodes=reach_nodes.replace(" ", ""); + System.out.println("Reachable Nodes:"+reach_nodes); + while (!end){ + int pointer=reach_nodes.indexOf(","); + if (pointer==-1) + end=true; + else { + String node=reach_nodes.substring(beginIndex, pointer); + System.out.println("Reachable Node:"+node); + reach_nodes=reach_nodes.substring(pointer+1); + nodes.add(node); + } + } + if (reach_nodes.length()>0){ + System.out.println("Reachable Node:"+reach_nodes); + nodes.add(reach_nodes); + } + return nodes; + } + + private void parseLinks(String dpid,String links, Hashtable nodes) //NOX Parse Links. it's not used in TREMA + { + try { + //log.info("Inside parseJSON"); + JSONParser parser = new JSONParser(); + Object obj = parser.parse(links); + + JSONArray msg = (JSONArray) obj; + Iterator iterator = msg.iterator(); + while (iterator.hasNext()) + { + JSONObject jsonObject = (JSONObject) iterator.next(); + //System.out.println(jsonObject.get("src-switch")); + IntraDomainEdge edge= new IntraDomainEdge(); + + String labels = (String) jsonObject.get("labels");//?? + String destnode = ((String) jsonObject.get("peer_node")).replace("-", ":"); + String type = (String) jsonObject.get("port_type"); + + RouterInfoPM source = nodes.get(dpid); + RouterInfoPM dest = nodes.get(destnode); + + //((SimpleTEDB)TEDB).getNetworkGraph().addVertex(source); + //((SimpleTEDB)TEDB).getNetworkGraph().addVertex(dest); + + System.out.println("Srcnode: "+dpid); + System.out.println("Dstnode: "+destnode); + + System.out.println("Srcport: "+jsonObject.get("port_id")); + System.out.println("Dstport: "+jsonObject.get("peer_port")); + + if ((dest!= null)&&(source!=null)){ + + + edge.setSrc_if_id(Long.parseLong((String)jsonObject.get("port_id"))); + edge.setDst_if_id(Long.parseLong((String)jsonObject.get("peer_port"))); + + edge.setType(type); + + // This is a big problem because info is not initialized from file + // and the controller doesn't give information about how many wlans + // the are + + TE_Information tE_info = new TE_Information(); + System.out.println("Labels: Original ("+labels+") and Parsed ("+labels.substring(labels.indexOf(",")+1,labels.indexOf("]"))+")"); + tE_info.setNumberWLANs(Integer.parseInt(labels.substring(labels.indexOf(",")+1,labels.indexOf("]")))); + tE_info.initWLANs(); + + if (interDomainFile != null) + { + completeTE_Information(tE_info, source.getRouterID(), dest.getRouterID()); + } + + edge.setTE_info(tE_info); + + + edge.setDirectional(true); + //Bidirectional case? See other TEDUpdaters. + + ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge); + + } else { + System.out.println("Link with an unknown node. Ingnoring..."); + } + //log.info("Edge added:"+edge); + //log.info(((SimpleTEDB)TEDB).getIntraDomainLinks().toString()); + } + //parseRemainingLinksFromXML(nodes); + + + } + catch (Exception e) + { + log.info(e.toString()); + } + } + + +// private void parseLinks(String links,Hashtable nodes) +// { +// try { +// //log.info("Inside parseJSON"); +// JSONParser parser = new JSONParser(); +// Object obj = parser.parse(links); +// +// JSONArray msg = (JSONArray) obj; +// Iterator iterator = msg.iterator(); +// while (iterator.hasNext()) +// { +// JSONObject jsonObject = (JSONObject) iterator.next(); +// //System.out.println(jsonObject.get("src-switch")); +// IntraDomainEdge edge= new IntraDomainEdge(); +// +// JSONObject jsonObject_src = (JSONObject) jsonObject.get("src"); +// JSONObject jsonObject_dst = (JSONObject) jsonObject.get("dst"); +// +// RouterInfoPM source = nodes.get(BristoltoFloodlight((String)jsonObject_src.get("dpid"))); +// RouterInfoPM dest = nodes.get(BristoltoFloodlight((String)jsonObject_dst.get("dpid"))); +// +// //((SimpleTEDB)TEDB).getNetworkGraph().addVertex(source); +// //((SimpleTEDB)TEDB).getNetworkGraph().addVertex(dest); +// +// log.info("Adding Vertex->"+source+" hashcode:"+source.hashCode()); +// log.info("Adding Vertex->"+dest+" hashcode:"+dest.hashCode()); +// +// edge.setSrc_if_id((Long)jsonObject_src.get("port_no")); +// edge.setDst_if_id((Long)jsonObject_dst.get("port_no")); +// +// +// // This is a big problem because info is not initialized from file +// // and the controller doesn't give information about how many wlans +// // the are +// +// TE_Information tE_info = new TE_Information(); +// tE_info.setNumberWLANs(15); +// tE_info.initWLANs(); +// +// if (interDomainFile != null) +// { +// completeTE_Information(tE_info, source.getRouterID(), dest.getRouterID()); +// } +// +// edge.setTE_info(tE_info); +// +// String isBidirectional = (String)jsonObject.get("direction"); +// +// +// // En Bristol los enlaces son unidirecctionales, pero asumimos que hay uno en una direccion +// // esta el otro +// isBidirectional = "bidirectional"; +// +// //log.info("isBidirectional::"+isBidirectional); +// +// if ((1==1)||(isBidirectional != null) && (isBidirectional.equals("bidirectional"))) +// { +// //((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge); +// +// TE_Information tE_infoOtherWay = new TE_Information(); +// tE_infoOtherWay.setNumberWLANs(15); +// tE_infoOtherWay.initWLANs(); +// IntraDomainEdge edgeOtherWay= new IntraDomainEdge(); +// +// edgeOtherWay.setSrc_if_id((Long)jsonObject_src.get("port_no")); +// edgeOtherWay.setDst_if_id((Long)jsonObject_dst.get("port_no")); +// edgeOtherWay.setTE_info(tE_infoOtherWay); +// +// ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge); +// ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(dest, source, edgeOtherWay); +// +// completeTE_Information(tE_info, dest.getRouterID(), source.getRouterID()); +// +// log.info("source::"+source); +// log.info("dest::"+dest); +// log.info("edgeOtherWay::"+edgeOtherWay); +// log.info("edge::"+edge); +// //log.info("Adding two!"); +// } +// else +// { +// ((SimpleTEDB)TEDB).getNetworkGraph().addEdge(source, dest, edge); +// } +// +// //log.info("Edge added:"+edge); +// //log.info(((SimpleTEDB)TEDB).getIntraDomainLinks().toString()); +// } +// //parseRemainingLinksFromXML(nodes); +// +// +// } +// catch (Exception e) +// { +// log.info(UtilsFunctions.exceptionToString(e)); +// } +// } + + private void completeTE_Information(TE_Information tE_info, String source, String dest) + { + MyEdge auxEdge = new MyEdge(source, dest); + MyEdge completEdge = interDomainLinks.get(auxEdge.hashCode()); + if ((completEdge != null)&&(completEdge.vlan != null)) + { + tE_info.setVlanLink(true); + tE_info.setVlan(completEdge.vlan); + //If it has been found it will be removed so the rest can be proccessed later + interDomainLinks.remove(completEdge.vlan); + } + else + { + tE_info.setVlanLink(false); + } + } + + private String queryForLinks(String ip, String port) + { + String response = ""; + try + { + URL topoplogyURL = new URL("http://"+ip+":"+port+topologyPathLinks); + + log.info("URL::"+"http://"+ip+":"+port+topologyPathLinks); + + URLConnection yc = topoplogyURL.openConnection(); + BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream())); + String inputLine; + + while ((inputLine = in.readLine()) != null) + { + response = response + inputLine; + } + } + catch (Exception e) + { + log.info(e.toString()); + } + return response; + } + + private String queryForNodes(String ip, String port) + { + String response = ""; + try + { + URL topoplogyURL = new URL("http://"+ip+":"+port+topologyPathNodes); + + log.info("http://+port+topologyPathNodes:::"+"http://"+ip+":"+port+topologyPathNodes); + + URLConnection yc = topoplogyURL.openConnection(); + BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream())); + + String inputLine; + while ((inputLine = in.readLine()) != null) + { + response = response + inputLine; + } + in.close(); + } + catch (Exception e) + { + log.info(e.toString()); + } + return response; + } + + public String getInterDomainFile() + { + return interDomainFile; + } + + public void setInterDomainFile(String interDomainFile) + { + this.interDomainFile = interDomainFile; + } + + + private void lock() + { + if (lock != null) + { + lock.lock(); + } + } + + private void unlock() + { + if (lock != null) + { + lock.unlock(); + } + } +} + diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/AuthInfo.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/AuthInfo.java new file mode 100644 index 000000000..aec4c98c0 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/AuthInfo.java @@ -0,0 +1,52 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb.elements; + +public class AuthInfo { + /**User ID to be used for authentication */ + private String userID; + + /**password assicoated with the user ID*/ + private String passwd; + + /** + * @return the userID + */ + public String getUserID() { + return userID; + } + + /** + * @param userID the userID to set + */ + public void setUserID(String userID) { + this.userID = userID; + } + + /** + * @return the passwd + */ + public String getPasswd() { + return passwd; + } + + /** + * @param passwd the passwd to set + */ + public void setPasswd(String passwd) { + this.passwd = passwd; + } + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Bandwidth.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Bandwidth.java new file mode 100644 index 000000000..0fb657e27 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/Bandwidth.java @@ -0,0 +1,63 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb.elements; + + public class Bandwidth { + + double maxBandwidth; + double unreservedBw; + + + public Bandwidth (double initBandwidth){ + maxBandwidth = initBandwidth; + unreservedBw = initBandwidth; + } + + + public Bandwidth (double max, double unresv){ + maxBandwidth = max; + unreservedBw = unresv; + } + + + public String toString(){ + return "Unreserved Bw = " + unreservedBw + ", Max Bandwidth = " + maxBandwidth; + } + + /** + * @return the maxBandwidth + */ + public double getMaxBandwidth() { + return maxBandwidth; + } + /** + * @param maxBandwidth the maxBandwidth to set + */ + public void setMaxBandwidth(double maxBandwidth) { + this.maxBandwidth = maxBandwidth; + } + /** + * @return the unreservedBw + */ + public double getUnreservedBw() { + return unreservedBw; + } + /** + * @param unreservedBw the unreservedBw to set + */ + public void setUnreservedBw(double unreservedBw) { + this.unreservedBw = unreservedBw; + } + } diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/BgpParams.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/BgpParams.java new file mode 100644 index 000000000..98c529e65 --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/BgpParams.java @@ -0,0 +1,19 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb.elements; + +public class BgpParams { + +} diff --git a/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/EndPoint.java b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/EndPoint.java new file mode 100644 index 000000000..27a4c0ffc --- /dev/null +++ b/src/bgpls_speaker/service/java/netphony-topology/src/main/java/eu/teraflow/tid/tedb/elements/EndPoint.java @@ -0,0 +1,81 @@ +// Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package eu.teraflow.tid.tedb.elements; + +public class EndPoint { + String node; + + String intf; + + public EndPoint(String node, String intf){ + this.node = node; + this.intf = intf; + } + + /** + * @return the node + */ + public String getNode() { + return node; + } + + /** + * @param node the node to set + */ + public void setNode(String node) { + this.node = node; + } + + /** + * @return the intf + */ + public String getIntf() { + return intf; + } + + /** + * @param intf the intf to set + */ + public void setIntf(String intf) { + this.intf = intf; + } + + + public int compareTo(EndPoint arg0) { + if ((arg0.intf.compareTo(this.intf)==0) && (arg0.node.compareTo(this.node)==0)) + return 0; + else + return 1; + } + @Override + public boolean equals(Object obj) { + if ((this.node.equals(((EndPoint)obj).getNode()))&& + (this.intf.equals(((EndPoint)obj).getIntf()))) + return true; + return false; + } + + @Override + public String toString() { + // TODO Auto-generated method stub + String temp=""; +