diff --git a/build.gradle b/build.gradle index 69718fb..1c2316e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,8 +1,8 @@ group 'ssbgp' -version '1.1.1' +version '1.2' buildscript { - ext.kotlin_version = '1.1.4-3' + ext.kotlin_version = '1.1.50' ext.dokka_version = '0.9.15' ext.junit_version = '1.0.0-M4' ext.junit5_version = '5.0.0-M4' diff --git a/src/main/kotlin/bgp/BGP.kt b/src/main/kotlin/bgp/BGP.kt index 55f4746..4107630 100644 --- a/src/main/kotlin/bgp/BGP.kt +++ b/src/main/kotlin/bgp/BGP.kt @@ -31,6 +31,12 @@ abstract class BaseBGP(val mrai: Time, routingTable: RoutingTable): Pr */ val routingTable = RouteSelector.wrap(routingTable, ::bgpRouteCompare) + /** + * The route selected by the protocol. + */ + override val selectedRoute: BGPRoute + get() = routingTable.getSelectedRoute() + var mraiTimer = Timer.disabled() protected set diff --git a/src/main/kotlin/core/routing/Protocol.kt b/src/main/kotlin/core/routing/Protocol.kt index 852717d..a03a998 100644 --- a/src/main/kotlin/core/routing/Protocol.kt +++ b/src/main/kotlin/core/routing/Protocol.kt @@ -10,6 +10,11 @@ interface Protocol { */ val inNeighbors: Collection> + /** + * The route selected by the protocol. + */ + val selectedRoute: R + /** * Adds a new in-neighbor for the protocol to consider. */ diff --git a/src/main/kotlin/core/simulator/Engine.kt b/src/main/kotlin/core/simulator/Engine.kt index e02cfd3..c615789 100644 --- a/src/main/kotlin/core/simulator/Engine.kt +++ b/src/main/kotlin/core/simulator/Engine.kt @@ -71,7 +71,7 @@ object Engine { event.processIt() } - BasicNotifier.notifyEnd(EndNotification()) + BasicNotifier.notifyEnd(EndNotification(topology)) return terminatedBeforeThreshold } diff --git a/src/main/kotlin/core/simulator/notifications/EndNotification.kt b/src/main/kotlin/core/simulator/notifications/EndNotification.kt index ff479ab..411044c 100644 --- a/src/main/kotlin/core/simulator/notifications/EndNotification.kt +++ b/src/main/kotlin/core/simulator/notifications/EndNotification.kt @@ -1,9 +1,11 @@ package core.simulator.notifications +import core.routing.Topology + /** * Created on 25-07-2017. * * @author David Fialho */ -class EndNotification : Notification() \ No newline at end of file +data class EndNotification(val topology: Topology<*>) : Notification() \ No newline at end of file diff --git a/src/main/kotlin/io/BasicReporter.kt b/src/main/kotlin/io/BasicReporter.kt index 6e7bd69..878c060 100644 --- a/src/main/kotlin/io/BasicReporter.kt +++ b/src/main/kotlin/io/BasicReporter.kt @@ -2,9 +2,7 @@ package io import simulation.BasicDataSet import java.io.File -import java.io.FileWriter import java.io.IOException -import java.io.Writer /** @@ -45,7 +43,8 @@ class BasicReporter(private val outputFile: File): Reporter { "Termination Time (Avg.)", "Message Count", "Detection Count", - "Terminated" + "Terminated", + "Disconnected Count" ) wereHeadersPrinted = true @@ -58,7 +57,8 @@ class BasicReporter(private val outputFile: File): Reporter { data.avgTerminationTime, data.messageCount, data.detectionCount, - if (data.terminated) "Yes" else "No" + if (data.terminated) "Yes" else "No", + data.disconnectedCount ) simulation++ diff --git a/src/main/kotlin/simulation/BasicDataCollector.kt b/src/main/kotlin/simulation/BasicDataCollector.kt index 7009446..502417a 100644 --- a/src/main/kotlin/simulation/BasicDataCollector.kt +++ b/src/main/kotlin/simulation/BasicDataCollector.kt @@ -18,17 +18,18 @@ import java.io.IOException * * @param reporter the reporter used to report the final data. */ -class BasicDataCollector(private val reporter: BasicReporter): DataCollector, +class BasicDataCollector(private val reporter: BasicReporter) : DataCollector, StartListener, MessageSentListener, ExportListener, DetectListener, - ThresholdReachedListener { + ThresholdReachedListener, + EndListener { /** * Creates a Basic Reporter that will output results to the specified output file. */ - constructor(outputFile: File): this(BasicReporter(outputFile)) + constructor(outputFile: File) : this(BasicReporter(outputFile)) /** * Stores the final data to be reported. @@ -57,6 +58,7 @@ class BasicDataCollector(private val reporter: BasicReporter): DataCollector, BGPNotifier.addExportListener(this) BGPNotifier.addDetectListener(this) BasicNotifier.addThresholdReachedListener(this) + BasicNotifier.addEndListener(this) } /** @@ -68,6 +70,7 @@ class BasicDataCollector(private val reporter: BasicReporter): DataCollector, BGPNotifier.removeExportListener(this) BGPNotifier.removeDetectListener(this) BasicNotifier.removeThresholdReachedListener(this) + BasicNotifier.removeEndListener(this) } /** @@ -138,5 +141,15 @@ class BasicDataCollector(private val reporter: BasicReporter): DataCollector, data.terminated = false } + /** + * Invoked to notify the listener of a new end notification. + */ + override fun notify(notification: EndNotification) { + + data.disconnectedCount = notification.topology.nodes + .filterNot { it.protocol.selectedRoute.isValid() } + .count() + } + // endregion } \ No newline at end of file diff --git a/src/main/kotlin/simulation/BasicDataSet.kt b/src/main/kotlin/simulation/BasicDataSet.kt index 1055176..10c627d 100644 --- a/src/main/kotlin/simulation/BasicDataSet.kt +++ b/src/main/kotlin/simulation/BasicDataSet.kt @@ -15,6 +15,7 @@ import core.simulator.Time * @property avgTerminationTime the average of the termination times of all nodes * @property detectionCount the number of detections recorded during the simulation. * @property terminated flag indicating if the simulation terminated or not + * @property disconnectedCount number of nodes left without a route when the simulation ended. */ data class BasicDataSet( var delaySeed: Long = 0L, @@ -22,7 +23,8 @@ data class BasicDataSet( var totalTerminationTime: Time = 0, var avgTerminationTime: Double = 0.0, var detectionCount: Int = 0, - var terminated: Boolean = true + var terminated: Boolean = true, + var disconnectedCount: Int = 0 ): DataSet { @@ -36,5 +38,6 @@ data class BasicDataSet( avgTerminationTime = 0.0 detectionCount = 0 terminated = true + disconnectedCount = 0 } } \ No newline at end of file diff --git a/src/test/kotlin/bgp/policies/interdomain/InterdomainCompareRoutesTests.kt b/src/test/kotlin/bgp/policies/interdomain/InterdomainCompareRoutesTests.kt index fa29a18..ec9cfe9 100644 --- a/src/test/kotlin/bgp/policies/interdomain/InterdomainCompareRoutesTests.kt +++ b/src/test/kotlin/bgp/policies/interdomain/InterdomainCompareRoutesTests.kt @@ -1,12 +1,12 @@ package bgp.policies.interdomain import bgp.bgpRouteCompare -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.it -import org.jetbrains.spek.api.dsl.on import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.* +import org.jetbrains.spek.api.Spek import org.jetbrains.spek.api.dsl.context +import org.jetbrains.spek.api.dsl.it +import org.jetbrains.spek.api.dsl.on import org.hamcrest.Matchers.`is` as Is @@ -51,6 +51,22 @@ object InterdomainCompareRoutesTests: Spek({ } } + on("comparing a customer route and a peer* route") { + + it("returns peer* route has higher preference") { + assertThat(bgpRouteCompare(peerstarRoute(), customerRoute()), + Is(greaterThan(0))) + } + } + + on("comparing a peer+ route and a peer* route") { + + it("returns peer+ route has higher preference") { + assertThat(bgpRouteCompare(peerplusRoute(), peerstarRoute()), + Is(greaterThan(0))) + } + } + on("comparing a customer route with 0 sibling hops with customer route with 1 sibling hop") { it("returns route with 0 sibling hops has higher preference") { diff --git a/src/test/kotlin/testing/Fakes.kt b/src/test/kotlin/testing/Fakes.kt index 4a12c3e..d76cdef 100644 --- a/src/test/kotlin/testing/Fakes.kt +++ b/src/test/kotlin/testing/Fakes.kt @@ -34,6 +34,9 @@ object FakeProtocol: Protocol { override val inNeighbors: Collection> get() = TODO("not implemented yet") + override val selectedRoute: Route + get() = TODO("not implemented yet") + override fun addInNeighbor(neighbor: Neighbor) { TODO("not implemented yet") }